11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * iSCSI transport class definitions
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) IBM Corporation, 2004
60896b752SAlex Aizman * Copyright (C) Mike Christie, 2004 - 2005
70896b752SAlex Aizman * Copyright (C) Dmitry Yusupov, 2004 - 2005
80896b752SAlex Aizman * Copyright (C) Alex Aizman, 2004 - 2005
91da177e4SLinus Torvalds */
101da177e4SLinus Torvalds #include <linux/module.h>
110b950672SArjan van de Ven #include <linux/mutex.h>
125a0e3ad6STejun Heo #include <linux/slab.h>
1390eeb01aSMike Christie #include <linux/bsg-lib.h>
148d4a690cSMike Christie #include <linux/idr.h>
150896b752SAlex Aizman #include <net/tcp.h>
161da177e4SLinus Torvalds #include <scsi/scsi.h>
171da177e4SLinus Torvalds #include <scsi/scsi_host.h>
181da177e4SLinus Torvalds #include <scsi/scsi_device.h>
191da177e4SLinus Torvalds #include <scsi/scsi_transport.h>
201da177e4SLinus Torvalds #include <scsi/scsi_transport_iscsi.h>
210896b752SAlex Aizman #include <scsi/iscsi_if.h>
22c01be6dcSMike Christie #include <scsi/scsi_cmnd.h>
2390eeb01aSMike Christie #include <scsi/scsi_bsg_iscsi.h>
241da177e4SLinus Torvalds
254c2133c8SMike Christie #define ISCSI_TRANSPORT_VERSION "2.0-870"
261da177e4SLinus Torvalds
27bba340c7SBo Wu #define ISCSI_SEND_MAX_ALLOWED 10
28bba340c7SBo Wu
29c2332b00SFred Herard #define CREATE_TRACE_POINTS
30c2332b00SFred Herard #include <trace/events/iscsi.h>
31c2332b00SFred Herard
32c2332b00SFred Herard /*
33c2332b00SFred Herard * Export tracepoint symbols to be used by other modules.
34c2332b00SFred Herard */
35c2332b00SFred Herard EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_conn);
36c2332b00SFred Herard EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_eh);
37c2332b00SFred Herard EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_session);
38c2332b00SFred Herard EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_tcp);
39c2332b00SFred Herard EXPORT_TRACEPOINT_SYMBOL_GPL(iscsi_dbg_sw_tcp);
40c2332b00SFred Herard
41632248aaSMike Christie static int dbg_session;
42632248aaSMike Christie module_param_named(debug_session, dbg_session, int,
43632248aaSMike Christie S_IRUGO | S_IWUSR);
44632248aaSMike Christie MODULE_PARM_DESC(debug_session,
45632248aaSMike Christie "Turn on debugging for sessions in scsi_transport_iscsi "
46632248aaSMike Christie "module. Set to 1 to turn on, and zero to turn off. Default "
47632248aaSMike Christie "is off.");
48632248aaSMike Christie
49632248aaSMike Christie static int dbg_conn;
50632248aaSMike Christie module_param_named(debug_conn, dbg_conn, int,
51632248aaSMike Christie S_IRUGO | S_IWUSR);
52632248aaSMike Christie MODULE_PARM_DESC(debug_conn,
53632248aaSMike Christie "Turn on debugging for connections in scsi_transport_iscsi "
54632248aaSMike Christie "module. Set to 1 to turn on, and zero to turn off. Default "
55632248aaSMike Christie "is off.");
56632248aaSMike Christie
57632248aaSMike Christie #define ISCSI_DBG_TRANS_SESSION(_session, dbg_fmt, arg...) \
58632248aaSMike Christie do { \
59632248aaSMike Christie if (dbg_session) \
60632248aaSMike Christie iscsi_cls_session_printk(KERN_INFO, _session, \
61632248aaSMike Christie "%s: " dbg_fmt, \
62632248aaSMike Christie __func__, ##arg); \
63c2332b00SFred Herard iscsi_dbg_trace(trace_iscsi_dbg_trans_session, \
64c2332b00SFred Herard &(_session)->dev, \
65c2332b00SFred Herard "%s " dbg_fmt, __func__, ##arg); \
66632248aaSMike Christie } while (0);
67632248aaSMike Christie
68632248aaSMike Christie #define ISCSI_DBG_TRANS_CONN(_conn, dbg_fmt, arg...) \
69632248aaSMike Christie do { \
70632248aaSMike Christie if (dbg_conn) \
71632248aaSMike Christie iscsi_cls_conn_printk(KERN_INFO, _conn, \
72632248aaSMike Christie "%s: " dbg_fmt, \
73632248aaSMike Christie __func__, ##arg); \
74c2332b00SFred Herard iscsi_dbg_trace(trace_iscsi_dbg_trans_conn, \
75c2332b00SFred Herard &(_conn)->dev, \
76c2332b00SFred Herard "%s " dbg_fmt, __func__, ##arg); \
77632248aaSMike Christie } while (0);
78632248aaSMike Christie
791da177e4SLinus Torvalds struct iscsi_internal {
801da177e4SLinus Torvalds struct scsi_transport_template t;
810896b752SAlex Aizman struct iscsi_transport *iscsi_transport;
820896b752SAlex Aizman struct list_head list;
83ee959b00STony Jones struct device dev;
8430a6c652SMike Christie
850896b752SAlex Aizman struct transport_container conn_cont;
860896b752SAlex Aizman struct transport_container session_cont;
871da177e4SLinus Torvalds };
881da177e4SLinus Torvalds
893c6ae371SMike Christie static DEFINE_IDR(iscsi_ep_idr);
903c6ae371SMike Christie static DEFINE_MUTEX(iscsi_ep_idr_mutex);
913c6ae371SMike Christie
9241be1444SMike Christie static atomic_t iscsi_session_nr; /* sysfs session id for next new session */
93b5c7a12dSMike Christie
9423d6fefbSMike Christie static struct workqueue_struct *iscsi_conn_cleanup_workq;
9523d6fefbSMike Christie
968d4a690cSMike Christie static DEFINE_IDA(iscsi_sess_ida);
970896b752SAlex Aizman /*
980896b752SAlex Aizman * list of registered transports and lock that must
990896b752SAlex Aizman * be held while accessing list. The iscsi_transport_lock must
1000b950672SArjan van de Ven * be acquired after the rx_queue_mutex.
1010896b752SAlex Aizman */
1020896b752SAlex Aizman static LIST_HEAD(iscsi_transports);
1030896b752SAlex Aizman static DEFINE_SPINLOCK(iscsi_transport_lock);
1041da177e4SLinus Torvalds
1050896b752SAlex Aizman #define to_iscsi_internal(tmpl) \
1060896b752SAlex Aizman container_of(tmpl, struct iscsi_internal, t)
1070896b752SAlex Aizman
108ee959b00STony Jones #define dev_to_iscsi_internal(_dev) \
109ee959b00STony Jones container_of(_dev, struct iscsi_internal, dev)
1100896b752SAlex Aizman
iscsi_transport_release(struct device * dev)111ee959b00STony Jones static void iscsi_transport_release(struct device *dev)
1120896b752SAlex Aizman {
113ee959b00STony Jones struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
1140896b752SAlex Aizman kfree(priv);
1150896b752SAlex Aizman }
1160896b752SAlex Aizman
1170896b752SAlex Aizman /*
1180896b752SAlex Aizman * iscsi_transport_class represents the iscsi_transports that are
1190896b752SAlex Aizman * registered.
1200896b752SAlex Aizman */
1210896b752SAlex Aizman static struct class iscsi_transport_class = {
1220896b752SAlex Aizman .name = "iscsi_transport",
123ee959b00STony Jones .dev_release = iscsi_transport_release,
1240896b752SAlex Aizman };
1250896b752SAlex Aizman
1260896b752SAlex Aizman static ssize_t
show_transport_handle(struct device * dev,struct device_attribute * attr,char * buf)127ee959b00STony Jones show_transport_handle(struct device *dev, struct device_attribute *attr,
128ee959b00STony Jones char *buf)
1290896b752SAlex Aizman {
130ee959b00STony Jones struct iscsi_internal *priv = dev_to_iscsi_internal(dev);
131688e8128SLee Duncan
132688e8128SLee Duncan if (!capable(CAP_SYS_ADMIN))
133688e8128SLee Duncan return -EACCES;
134ec98ea70SChris Leech return sysfs_emit(buf, "%llu\n",
135ec98ea70SChris Leech (unsigned long long)iscsi_handle(priv->iscsi_transport));
1360896b752SAlex Aizman }
137ee959b00STony Jones static DEVICE_ATTR(handle, S_IRUGO, show_transport_handle, NULL);
1380896b752SAlex Aizman
1390896b752SAlex Aizman #define show_transport_attr(name, format) \
1400896b752SAlex Aizman static ssize_t \
141ee959b00STony Jones show_transport_##name(struct device *dev, \
142ee959b00STony Jones struct device_attribute *attr,char *buf) \
1430896b752SAlex Aizman { \
144ee959b00STony Jones struct iscsi_internal *priv = dev_to_iscsi_internal(dev); \
145ec98ea70SChris Leech return sysfs_emit(buf, format"\n", priv->iscsi_transport->name);\
1460896b752SAlex Aizman } \
147ee959b00STony Jones static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);
1480896b752SAlex Aizman
1490896b752SAlex Aizman show_transport_attr(caps, "0x%x");
1500896b752SAlex Aizman
1510896b752SAlex Aizman static struct attribute *iscsi_transport_attrs[] = {
152ee959b00STony Jones &dev_attr_handle.attr,
153ee959b00STony Jones &dev_attr_caps.attr,
1540896b752SAlex Aizman NULL,
1550896b752SAlex Aizman };
1560896b752SAlex Aizman
1570896b752SAlex Aizman static struct attribute_group iscsi_transport_group = {
1580896b752SAlex Aizman .attrs = iscsi_transport_attrs,
1590896b752SAlex Aizman };
1600896b752SAlex Aizman
161d82ff9beSMike Christie /*
162d82ff9beSMike Christie * iSCSI endpoint attrs
163d82ff9beSMike Christie */
164d82ff9beSMike Christie #define iscsi_dev_to_endpoint(_dev) \
165d82ff9beSMike Christie container_of(_dev, struct iscsi_endpoint, dev)
166d82ff9beSMike Christie
167d82ff9beSMike Christie #define ISCSI_ATTR(_prefix,_name,_mode,_show,_store) \
168d82ff9beSMike Christie struct device_attribute dev_attr_##_prefix##_##_name = \
169d82ff9beSMike Christie __ATTR(_name,_mode,_show,_store)
170d82ff9beSMike Christie
iscsi_endpoint_release(struct device * dev)171d82ff9beSMike Christie static void iscsi_endpoint_release(struct device *dev)
172d82ff9beSMike Christie {
173d82ff9beSMike Christie struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
1743c6ae371SMike Christie
1753c6ae371SMike Christie mutex_lock(&iscsi_ep_idr_mutex);
1763c6ae371SMike Christie idr_remove(&iscsi_ep_idr, ep->id);
1773c6ae371SMike Christie mutex_unlock(&iscsi_ep_idr_mutex);
1783c6ae371SMike Christie
179d82ff9beSMike Christie kfree(ep);
180d82ff9beSMike Christie }
181d82ff9beSMike Christie
182d82ff9beSMike Christie static struct class iscsi_endpoint_class = {
183d82ff9beSMike Christie .name = "iscsi_endpoint",
184d82ff9beSMike Christie .dev_release = iscsi_endpoint_release,
185d82ff9beSMike Christie };
186d82ff9beSMike Christie
187d82ff9beSMike Christie static ssize_t
show_ep_handle(struct device * dev,struct device_attribute * attr,char * buf)188d82ff9beSMike Christie show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
189d82ff9beSMike Christie {
190d82ff9beSMike Christie struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
1913c6ae371SMike Christie return sysfs_emit(buf, "%d\n", ep->id);
192d82ff9beSMike Christie }
193d82ff9beSMike Christie static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
194d82ff9beSMike Christie
195d82ff9beSMike Christie static struct attribute *iscsi_endpoint_attrs[] = {
196d82ff9beSMike Christie &dev_attr_ep_handle.attr,
197d82ff9beSMike Christie NULL,
198d82ff9beSMike Christie };
199d82ff9beSMike Christie
200d82ff9beSMike Christie static struct attribute_group iscsi_endpoint_group = {
201d82ff9beSMike Christie .attrs = iscsi_endpoint_attrs,
202d82ff9beSMike Christie };
203d82ff9beSMike Christie
204d82ff9beSMike Christie struct iscsi_endpoint *
iscsi_create_endpoint(int dd_size)205d82ff9beSMike Christie iscsi_create_endpoint(int dd_size)
206d82ff9beSMike Christie {
207d82ff9beSMike Christie struct iscsi_endpoint *ep;
2083c6ae371SMike Christie int err, id;
209d82ff9beSMike Christie
210d82ff9beSMike Christie ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
211d82ff9beSMike Christie if (!ep)
212d82ff9beSMike Christie return NULL;
213d82ff9beSMike Christie
2143c6ae371SMike Christie mutex_lock(&iscsi_ep_idr_mutex);
215f6eed15fSSergey Gorenko
216f6eed15fSSergey Gorenko /*
217f6eed15fSSergey Gorenko * First endpoint id should be 1 to comply with user space
218f6eed15fSSergey Gorenko * applications (iscsid).
219f6eed15fSSergey Gorenko */
220f6eed15fSSergey Gorenko id = idr_alloc(&iscsi_ep_idr, ep, 1, -1, GFP_NOIO);
2213c6ae371SMike Christie if (id < 0) {
2223c6ae371SMike Christie mutex_unlock(&iscsi_ep_idr_mutex);
2233c6ae371SMike Christie printk(KERN_ERR "Could not allocate endpoint ID. Error %d.\n",
2243c6ae371SMike Christie id);
2253c6ae371SMike Christie goto free_ep;
2263c6ae371SMike Christie }
2273c6ae371SMike Christie mutex_unlock(&iscsi_ep_idr_mutex);
2283c6ae371SMike Christie
229d82ff9beSMike Christie ep->id = id;
230d82ff9beSMike Christie ep->dev.class = &iscsi_endpoint_class;
2313c6ae371SMike Christie dev_set_name(&ep->dev, "ep-%d", id);
232d82ff9beSMike Christie err = device_register(&ep->dev);
233d82ff9beSMike Christie if (err)
234f014165fSZhou Guanghui goto put_dev;
235d82ff9beSMike Christie
236d82ff9beSMike Christie err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
237d82ff9beSMike Christie if (err)
238d82ff9beSMike Christie goto unregister_dev;
239d82ff9beSMike Christie
240d82ff9beSMike Christie if (dd_size)
241d82ff9beSMike Christie ep->dd_data = &ep[1];
242d82ff9beSMike Christie return ep;
243d82ff9beSMike Christie
244d82ff9beSMike Christie unregister_dev:
245d82ff9beSMike Christie device_unregister(&ep->dev);
246d82ff9beSMike Christie return NULL;
247d82ff9beSMike Christie
248f014165fSZhou Guanghui put_dev:
2493c6ae371SMike Christie mutex_lock(&iscsi_ep_idr_mutex);
2503c6ae371SMike Christie idr_remove(&iscsi_ep_idr, id);
2513c6ae371SMike Christie mutex_unlock(&iscsi_ep_idr_mutex);
252f014165fSZhou Guanghui put_device(&ep->dev);
253f014165fSZhou Guanghui return NULL;
254d82ff9beSMike Christie free_ep:
255d82ff9beSMike Christie kfree(ep);
256d82ff9beSMike Christie return NULL;
257d82ff9beSMike Christie }
258d82ff9beSMike Christie EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
259d82ff9beSMike Christie
iscsi_destroy_endpoint(struct iscsi_endpoint * ep)260d82ff9beSMike Christie void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
261d82ff9beSMike Christie {
262d82ff9beSMike Christie sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
263d82ff9beSMike Christie device_unregister(&ep->dev);
264d82ff9beSMike Christie }
265d82ff9beSMike Christie EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
266d82ff9beSMike Christie
iscsi_put_endpoint(struct iscsi_endpoint * ep)2679e5fe170SMike Christie void iscsi_put_endpoint(struct iscsi_endpoint *ep)
2689e5fe170SMike Christie {
2699e5fe170SMike Christie put_device(&ep->dev);
2709e5fe170SMike Christie }
2719e5fe170SMike Christie EXPORT_SYMBOL_GPL(iscsi_put_endpoint);
2729e5fe170SMike Christie
2739e5fe170SMike Christie /**
2749e5fe170SMike Christie * iscsi_lookup_endpoint - get ep from handle
2759e5fe170SMike Christie * @handle: endpoint handle
2769e5fe170SMike Christie *
2779e5fe170SMike Christie * Caller must do a iscsi_put_endpoint.
2789e5fe170SMike Christie */
iscsi_lookup_endpoint(u64 handle)279d82ff9beSMike Christie struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
280d82ff9beSMike Christie {
2813c6ae371SMike Christie struct iscsi_endpoint *ep;
282d82ff9beSMike Christie
2833c6ae371SMike Christie mutex_lock(&iscsi_ep_idr_mutex);
2843c6ae371SMike Christie ep = idr_find(&iscsi_ep_idr, handle);
2853c6ae371SMike Christie if (!ep)
2863c6ae371SMike Christie goto unlock;
287d82ff9beSMike Christie
2883c6ae371SMike Christie get_device(&ep->dev);
2893c6ae371SMike Christie unlock:
2903c6ae371SMike Christie mutex_unlock(&iscsi_ep_idr_mutex);
2913c6ae371SMike Christie return ep;
292d82ff9beSMike Christie }
293d82ff9beSMike Christie EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
294d82ff9beSMike Christie
2958d07913dSMike Christie /*
2968d07913dSMike Christie * Interface to display network param to sysfs
2978d07913dSMike Christie */
2988d07913dSMike Christie
iscsi_iface_release(struct device * dev)2998d07913dSMike Christie static void iscsi_iface_release(struct device *dev)
3008d07913dSMike Christie {
3018d07913dSMike Christie struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
3028d07913dSMike Christie struct device *parent = iface->dev.parent;
3038d07913dSMike Christie
3048d07913dSMike Christie kfree(iface);
3058d07913dSMike Christie put_device(parent);
3068d07913dSMike Christie }
3078d07913dSMike Christie
3088d07913dSMike Christie
3098d07913dSMike Christie static struct class iscsi_iface_class = {
3108d07913dSMike Christie .name = "iscsi_iface",
3118d07913dSMike Christie .dev_release = iscsi_iface_release,
3128d07913dSMike Christie };
3138d07913dSMike Christie
3148d07913dSMike Christie #define ISCSI_IFACE_ATTR(_prefix, _name, _mode, _show, _store) \
3158d07913dSMike Christie struct device_attribute dev_attr_##_prefix##_##_name = \
3168d07913dSMike Christie __ATTR(_name, _mode, _show, _store)
3178d07913dSMike Christie
3188d07913dSMike Christie /* iface attrs show */
3198d07913dSMike Christie #define iscsi_iface_attr_show(type, name, param_type, param) \
3208d07913dSMike Christie static ssize_t \
3218d07913dSMike Christie show_##type##_##name(struct device *dev, struct device_attribute *attr, \
3228d07913dSMike Christie char *buf) \
3238d07913dSMike Christie { \
3248d07913dSMike Christie struct iscsi_iface *iface = iscsi_dev_to_iface(dev); \
3258d07913dSMike Christie struct iscsi_transport *t = iface->transport; \
3268d07913dSMike Christie return t->get_iface_param(iface, param_type, param, buf); \
3278d07913dSMike Christie } \
3288d07913dSMike Christie
3298d07913dSMike Christie #define iscsi_iface_net_attr(type, name, param) \
3308d07913dSMike Christie iscsi_iface_attr_show(type, name, ISCSI_NET_PARAM, param) \
3318d07913dSMike Christie static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
3328d07913dSMike Christie
3333e0f65b3SHarish Zunjarrao #define iscsi_iface_attr(type, name, param) \
3343e0f65b3SHarish Zunjarrao iscsi_iface_attr_show(type, name, ISCSI_IFACE_PARAM, param) \
3353e0f65b3SHarish Zunjarrao static ISCSI_IFACE_ATTR(type, name, S_IRUGO, show_##type##_##name, NULL);
3363e0f65b3SHarish Zunjarrao
3373e0f65b3SHarish Zunjarrao /* generic read only ipv4 attribute */
3388d07913dSMike Christie iscsi_iface_net_attr(ipv4_iface, ipaddress, ISCSI_NET_PARAM_IPV4_ADDR);
3398d07913dSMike Christie iscsi_iface_net_attr(ipv4_iface, gateway, ISCSI_NET_PARAM_IPV4_GW);
3408d07913dSMike Christie iscsi_iface_net_attr(ipv4_iface, subnet, ISCSI_NET_PARAM_IPV4_SUBNET);
3418d07913dSMike Christie iscsi_iface_net_attr(ipv4_iface, bootproto, ISCSI_NET_PARAM_IPV4_BOOTPROTO);
3423e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, dhcp_dns_address_en,
3433e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN);
3443e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, dhcp_slp_da_info_en,
3453e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN);
3463e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, tos_en, ISCSI_NET_PARAM_IPV4_TOS_EN);
3473e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, tos, ISCSI_NET_PARAM_IPV4_TOS);
3483e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, grat_arp_en,
3493e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN);
3503e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, dhcp_alt_client_id_en,
3513e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN);
3523e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, dhcp_alt_client_id,
3533e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID);
3543e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, dhcp_req_vendor_id_en,
3553e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN);
3563e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, dhcp_use_vendor_id_en,
3573e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN);
3583e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, dhcp_vendor_id,
3593e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID);
3603e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, dhcp_learn_iqn_en,
3613e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN);
3623e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, fragment_disable,
3633e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE);
3643e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, incoming_forwarding_en,
3653e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN);
3663e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv4_iface, ttl, ISCSI_NET_PARAM_IPV4_TTL);
3678d07913dSMike Christie
3688d07913dSMike Christie /* generic read only ipv6 attribute */
3698d07913dSMike Christie iscsi_iface_net_attr(ipv6_iface, ipaddress, ISCSI_NET_PARAM_IPV6_ADDR);
3703e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, link_local_addr,
3713e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_LINKLOCAL);
3728d07913dSMike Christie iscsi_iface_net_attr(ipv6_iface, router_addr, ISCSI_NET_PARAM_IPV6_ROUTER);
3738d07913dSMike Christie iscsi_iface_net_attr(ipv6_iface, ipaddr_autocfg,
3748d07913dSMike Christie ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG);
37588f4f517SMike Christie iscsi_iface_net_attr(ipv6_iface, link_local_autocfg,
3768d07913dSMike Christie ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG);
3773e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, link_local_state,
3783e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE);
3793e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, router_state,
3803e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_ROUTER_STATE);
3813e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, grat_neighbor_adv_en,
3823e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN);
3833e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, mld_en, ISCSI_NET_PARAM_IPV6_MLD_EN);
3843e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, flow_label, ISCSI_NET_PARAM_IPV6_FLOW_LABEL);
3853e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, traffic_class,
3863e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS);
3873e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, hop_limit, ISCSI_NET_PARAM_IPV6_HOP_LIMIT);
3883e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, nd_reachable_tmo,
3893e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO);
3903e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, nd_rexmit_time,
3913e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME);
3923e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, nd_stale_tmo,
3933e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_ND_STALE_TMO);
3943e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, dup_addr_detect_cnt,
3953e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT);
3963e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(ipv6_iface, router_adv_link_mtu,
3973e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU);
3988d07913dSMike Christie
3998d07913dSMike Christie /* common read only iface attribute */
4008d07913dSMike Christie iscsi_iface_net_attr(iface, enabled, ISCSI_NET_PARAM_IFACE_ENABLE);
4012d63673bSMike Christie iscsi_iface_net_attr(iface, vlan_id, ISCSI_NET_PARAM_VLAN_ID);
4024223b9e9SMike Christie iscsi_iface_net_attr(iface, vlan_priority, ISCSI_NET_PARAM_VLAN_PRIORITY);
4034223b9e9SMike Christie iscsi_iface_net_attr(iface, vlan_enabled, ISCSI_NET_PARAM_VLAN_ENABLED);
4048c7d40fbSVikas Chaudhary iscsi_iface_net_attr(iface, mtu, ISCSI_NET_PARAM_MTU);
405fcb5124eSVikas Chaudhary iscsi_iface_net_attr(iface, port, ISCSI_NET_PARAM_PORT);
4063e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(iface, ipaddress_state, ISCSI_NET_PARAM_IPADDR_STATE);
4073e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(iface, delayed_ack_en, ISCSI_NET_PARAM_DELAYED_ACK_EN);
4083e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(iface, tcp_nagle_disable,
4093e0f65b3SHarish Zunjarrao ISCSI_NET_PARAM_TCP_NAGLE_DISABLE);
4103e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(iface, tcp_wsf_disable, ISCSI_NET_PARAM_TCP_WSF_DISABLE);
4113e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(iface, tcp_wsf, ISCSI_NET_PARAM_TCP_WSF);
4123e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(iface, tcp_timer_scale, ISCSI_NET_PARAM_TCP_TIMER_SCALE);
4133e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(iface, tcp_timestamp_en, ISCSI_NET_PARAM_TCP_TIMESTAMP_EN);
4143e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(iface, cache_id, ISCSI_NET_PARAM_CACHE_ID);
4153e0f65b3SHarish Zunjarrao iscsi_iface_net_attr(iface, redirect_en, ISCSI_NET_PARAM_REDIRECT_EN);
4163e0f65b3SHarish Zunjarrao
4173e0f65b3SHarish Zunjarrao /* common iscsi specific settings attributes */
4183e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, def_taskmgmt_tmo, ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO);
4193e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, header_digest, ISCSI_IFACE_PARAM_HDRDGST_EN);
4203e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, data_digest, ISCSI_IFACE_PARAM_DATADGST_EN);
4213e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, immediate_data, ISCSI_IFACE_PARAM_IMM_DATA_EN);
4223e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, initial_r2t, ISCSI_IFACE_PARAM_INITIAL_R2T_EN);
4233e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, data_seq_in_order,
4243e0f65b3SHarish Zunjarrao ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN);
4253e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, data_pdu_in_order, ISCSI_IFACE_PARAM_PDU_INORDER_EN);
4263e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, erl, ISCSI_IFACE_PARAM_ERL);
4273e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, max_recv_dlength, ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH);
4283e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, first_burst_len, ISCSI_IFACE_PARAM_FIRST_BURST);
4293e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, max_outstanding_r2t, ISCSI_IFACE_PARAM_MAX_R2T);
4303e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, max_burst_len, ISCSI_IFACE_PARAM_MAX_BURST);
4313e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, chap_auth, ISCSI_IFACE_PARAM_CHAP_AUTH_EN);
4323e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, bidi_chap, ISCSI_IFACE_PARAM_BIDI_CHAP_EN);
4333e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, discovery_auth_optional,
4343e0f65b3SHarish Zunjarrao ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL);
4353e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, discovery_logout,
4363e0f65b3SHarish Zunjarrao ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN);
4373e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, strict_login_comp_en,
4383e0f65b3SHarish Zunjarrao ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN);
4393e0f65b3SHarish Zunjarrao iscsi_iface_attr(iface, initiator_name, ISCSI_IFACE_PARAM_INITIATOR_NAME);
4408d07913dSMike Christie
iscsi_iface_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)441587a1f16SAl Viro static umode_t iscsi_iface_attr_is_visible(struct kobject *kobj,
4428d07913dSMike Christie struct attribute *attr, int i)
4438d07913dSMike Christie {
4448d07913dSMike Christie struct device *dev = container_of(kobj, struct device, kobj);
4458d07913dSMike Christie struct iscsi_iface *iface = iscsi_dev_to_iface(dev);
4468d07913dSMike Christie struct iscsi_transport *t = iface->transport;
447e746f345SMike Christie int param = -1;
4488d07913dSMike Christie
4494e285508SBaokun Li if (attr == &dev_attr_iface_def_taskmgmt_tmo.attr)
4503e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_DEF_TASKMGMT_TMO;
4513e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_header_digest.attr)
4523e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_HDRDGST_EN;
4533e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_data_digest.attr)
4543e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_DATADGST_EN;
4553e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_immediate_data.attr)
4563e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_IMM_DATA_EN;
4573e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_initial_r2t.attr)
4583e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_INITIAL_R2T_EN;
4593e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_data_seq_in_order.attr)
4603e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_DATASEQ_INORDER_EN;
4613e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_data_pdu_in_order.attr)
4623e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_PDU_INORDER_EN;
4633e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_erl.attr)
4643e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_ERL;
4653e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_max_recv_dlength.attr)
4663e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_MAX_RECV_DLENGTH;
4673e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_first_burst_len.attr)
4683e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_FIRST_BURST;
4693e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_max_outstanding_r2t.attr)
4703e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_MAX_R2T;
4713e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_max_burst_len.attr)
4723e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_MAX_BURST;
4733e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_chap_auth.attr)
4743e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_CHAP_AUTH_EN;
4753e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_bidi_chap.attr)
4763e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_BIDI_CHAP_EN;
4773e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_discovery_auth_optional.attr)
4783e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_DISCOVERY_AUTH_OPTIONAL;
4793e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_discovery_logout.attr)
4803e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_DISCOVERY_LOGOUT_EN;
4813e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_strict_login_comp_en.attr)
4823e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_STRICT_LOGIN_COMP_EN;
4833e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_iface_initiator_name.attr)
4843e0f65b3SHarish Zunjarrao param = ISCSI_IFACE_PARAM_INITIATOR_NAME;
485e746f345SMike Christie
486e746f345SMike Christie if (param != -1)
487e746f345SMike Christie return t->attr_is_visible(ISCSI_IFACE_PARAM, param);
488e746f345SMike Christie
4894e285508SBaokun Li if (attr == &dev_attr_iface_enabled.attr)
4904e285508SBaokun Li param = ISCSI_NET_PARAM_IFACE_ENABLE;
4914e285508SBaokun Li else if (attr == &dev_attr_iface_vlan_id.attr)
492e746f345SMike Christie param = ISCSI_NET_PARAM_VLAN_ID;
493e746f345SMike Christie else if (attr == &dev_attr_iface_vlan_priority.attr)
494e746f345SMike Christie param = ISCSI_NET_PARAM_VLAN_PRIORITY;
495e746f345SMike Christie else if (attr == &dev_attr_iface_vlan_enabled.attr)
496e746f345SMike Christie param = ISCSI_NET_PARAM_VLAN_ENABLED;
497e746f345SMike Christie else if (attr == &dev_attr_iface_mtu.attr)
498e746f345SMike Christie param = ISCSI_NET_PARAM_MTU;
499e746f345SMike Christie else if (attr == &dev_attr_iface_port.attr)
500e746f345SMike Christie param = ISCSI_NET_PARAM_PORT;
501e746f345SMike Christie else if (attr == &dev_attr_iface_ipaddress_state.attr)
502e746f345SMike Christie param = ISCSI_NET_PARAM_IPADDR_STATE;
503e746f345SMike Christie else if (attr == &dev_attr_iface_delayed_ack_en.attr)
504e746f345SMike Christie param = ISCSI_NET_PARAM_DELAYED_ACK_EN;
505e746f345SMike Christie else if (attr == &dev_attr_iface_tcp_nagle_disable.attr)
506e746f345SMike Christie param = ISCSI_NET_PARAM_TCP_NAGLE_DISABLE;
507e746f345SMike Christie else if (attr == &dev_attr_iface_tcp_wsf_disable.attr)
508e746f345SMike Christie param = ISCSI_NET_PARAM_TCP_WSF_DISABLE;
509e746f345SMike Christie else if (attr == &dev_attr_iface_tcp_wsf.attr)
510e746f345SMike Christie param = ISCSI_NET_PARAM_TCP_WSF;
511e746f345SMike Christie else if (attr == &dev_attr_iface_tcp_timer_scale.attr)
512e746f345SMike Christie param = ISCSI_NET_PARAM_TCP_TIMER_SCALE;
513e746f345SMike Christie else if (attr == &dev_attr_iface_tcp_timestamp_en.attr)
514e746f345SMike Christie param = ISCSI_NET_PARAM_TCP_TIMESTAMP_EN;
515e746f345SMike Christie else if (attr == &dev_attr_iface_cache_id.attr)
516e746f345SMike Christie param = ISCSI_NET_PARAM_CACHE_ID;
517e746f345SMike Christie else if (attr == &dev_attr_iface_redirect_en.attr)
518e746f345SMike Christie param = ISCSI_NET_PARAM_REDIRECT_EN;
519b78dbba0SMike Christie else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV4) {
5208d07913dSMike Christie if (attr == &dev_attr_ipv4_iface_ipaddress.attr)
521b78dbba0SMike Christie param = ISCSI_NET_PARAM_IPV4_ADDR;
5228d07913dSMike Christie else if (attr == &dev_attr_ipv4_iface_gateway.attr)
523b78dbba0SMike Christie param = ISCSI_NET_PARAM_IPV4_GW;
5248d07913dSMike Christie else if (attr == &dev_attr_ipv4_iface_subnet.attr)
525b78dbba0SMike Christie param = ISCSI_NET_PARAM_IPV4_SUBNET;
5268d07913dSMike Christie else if (attr == &dev_attr_ipv4_iface_bootproto.attr)
527b78dbba0SMike Christie param = ISCSI_NET_PARAM_IPV4_BOOTPROTO;
5283e0f65b3SHarish Zunjarrao else if (attr ==
5293e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_dns_address_en.attr)
5303e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_DHCP_DNS_ADDR_EN;
5313e0f65b3SHarish Zunjarrao else if (attr ==
5323e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_slp_da_info_en.attr)
5333e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_DHCP_SLP_DA_EN;
5343e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv4_iface_tos_en.attr)
5353e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_TOS_EN;
5363e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv4_iface_tos.attr)
5373e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_TOS;
5383e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv4_iface_grat_arp_en.attr)
5393e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_GRAT_ARP_EN;
5403e0f65b3SHarish Zunjarrao else if (attr ==
5413e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_alt_client_id_en.attr)
5423e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID_EN;
5433e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv4_iface_dhcp_alt_client_id.attr)
5443e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_DHCP_ALT_CLIENT_ID;
5453e0f65b3SHarish Zunjarrao else if (attr ==
5463e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_req_vendor_id_en.attr)
5473e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_DHCP_REQ_VENDOR_ID_EN;
5483e0f65b3SHarish Zunjarrao else if (attr ==
5493e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_use_vendor_id_en.attr)
5503e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_DHCP_USE_VENDOR_ID_EN;
5513e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv4_iface_dhcp_vendor_id.attr)
5523e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_DHCP_VENDOR_ID;
5533e0f65b3SHarish Zunjarrao else if (attr ==
5543e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_learn_iqn_en.attr)
5553e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_DHCP_LEARN_IQN_EN;
5563e0f65b3SHarish Zunjarrao else if (attr ==
5573e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_fragment_disable.attr)
5583e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_FRAGMENT_DISABLE;
5593e0f65b3SHarish Zunjarrao else if (attr ==
5603e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_incoming_forwarding_en.attr)
5613e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_IN_FORWARD_EN;
5623e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv4_iface_ttl.attr)
5633e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV4_TTL;
564b78dbba0SMike Christie else
565b78dbba0SMike Christie return 0;
5668d07913dSMike Christie } else if (iface->iface_type == ISCSI_IFACE_TYPE_IPV6) {
5678d07913dSMike Christie if (attr == &dev_attr_ipv6_iface_ipaddress.attr)
568b78dbba0SMike Christie param = ISCSI_NET_PARAM_IPV6_ADDR;
5698d07913dSMike Christie else if (attr == &dev_attr_ipv6_iface_link_local_addr.attr)
570b78dbba0SMike Christie param = ISCSI_NET_PARAM_IPV6_LINKLOCAL;
5718d07913dSMike Christie else if (attr == &dev_attr_ipv6_iface_router_addr.attr)
572b78dbba0SMike Christie param = ISCSI_NET_PARAM_IPV6_ROUTER;
5738d07913dSMike Christie else if (attr == &dev_attr_ipv6_iface_ipaddr_autocfg.attr)
574b78dbba0SMike Christie param = ISCSI_NET_PARAM_IPV6_ADDR_AUTOCFG;
57588f4f517SMike Christie else if (attr == &dev_attr_ipv6_iface_link_local_autocfg.attr)
576b78dbba0SMike Christie param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_AUTOCFG;
5773e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_link_local_state.attr)
5783e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_LINKLOCAL_STATE;
5793e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_router_state.attr)
5803e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_ROUTER_STATE;
5813e0f65b3SHarish Zunjarrao else if (attr ==
5823e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_grat_neighbor_adv_en.attr)
5833e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_GRAT_NEIGHBOR_ADV_EN;
5843e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_mld_en.attr)
5853e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_MLD_EN;
5863e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_flow_label.attr)
5873e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_FLOW_LABEL;
5883e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_traffic_class.attr)
5893e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_TRAFFIC_CLASS;
5903e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_hop_limit.attr)
5913e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_HOP_LIMIT;
5923e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_nd_reachable_tmo.attr)
5933e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_ND_REACHABLE_TMO;
5943e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_nd_rexmit_time.attr)
5953e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_ND_REXMIT_TIME;
5963e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_nd_stale_tmo.attr)
5973e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_ND_STALE_TMO;
5983e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_dup_addr_detect_cnt.attr)
5993e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_DUP_ADDR_DETECT_CNT;
6003e0f65b3SHarish Zunjarrao else if (attr == &dev_attr_ipv6_iface_router_adv_link_mtu.attr)
6013e0f65b3SHarish Zunjarrao param = ISCSI_NET_PARAM_IPV6_RTR_ADV_LINK_MTU;
602b78dbba0SMike Christie else
603b78dbba0SMike Christie return 0;
604b78dbba0SMike Christie } else {
605b78dbba0SMike Christie WARN_ONCE(1, "Invalid iface attr");
606b78dbba0SMike Christie return 0;
6078d07913dSMike Christie }
6088d07913dSMike Christie
609e746f345SMike Christie return t->attr_is_visible(ISCSI_NET_PARAM, param);
6108d07913dSMike Christie }
6118d07913dSMike Christie
6128d07913dSMike Christie static struct attribute *iscsi_iface_attrs[] = {
6138d07913dSMike Christie &dev_attr_iface_enabled.attr,
6142d63673bSMike Christie &dev_attr_iface_vlan_id.attr,
6154223b9e9SMike Christie &dev_attr_iface_vlan_priority.attr,
6164223b9e9SMike Christie &dev_attr_iface_vlan_enabled.attr,
6178d07913dSMike Christie &dev_attr_ipv4_iface_ipaddress.attr,
6188d07913dSMike Christie &dev_attr_ipv4_iface_gateway.attr,
6198d07913dSMike Christie &dev_attr_ipv4_iface_subnet.attr,
6208d07913dSMike Christie &dev_attr_ipv4_iface_bootproto.attr,
6218d07913dSMike Christie &dev_attr_ipv6_iface_ipaddress.attr,
6228d07913dSMike Christie &dev_attr_ipv6_iface_link_local_addr.attr,
6238d07913dSMike Christie &dev_attr_ipv6_iface_router_addr.attr,
6248d07913dSMike Christie &dev_attr_ipv6_iface_ipaddr_autocfg.attr,
62588f4f517SMike Christie &dev_attr_ipv6_iface_link_local_autocfg.attr,
6268c7d40fbSVikas Chaudhary &dev_attr_iface_mtu.attr,
627fcb5124eSVikas Chaudhary &dev_attr_iface_port.attr,
6283e0f65b3SHarish Zunjarrao &dev_attr_iface_ipaddress_state.attr,
6293e0f65b3SHarish Zunjarrao &dev_attr_iface_delayed_ack_en.attr,
6303e0f65b3SHarish Zunjarrao &dev_attr_iface_tcp_nagle_disable.attr,
6313e0f65b3SHarish Zunjarrao &dev_attr_iface_tcp_wsf_disable.attr,
6323e0f65b3SHarish Zunjarrao &dev_attr_iface_tcp_wsf.attr,
6333e0f65b3SHarish Zunjarrao &dev_attr_iface_tcp_timer_scale.attr,
6343e0f65b3SHarish Zunjarrao &dev_attr_iface_tcp_timestamp_en.attr,
6353e0f65b3SHarish Zunjarrao &dev_attr_iface_cache_id.attr,
6363e0f65b3SHarish Zunjarrao &dev_attr_iface_redirect_en.attr,
6373e0f65b3SHarish Zunjarrao &dev_attr_iface_def_taskmgmt_tmo.attr,
6383e0f65b3SHarish Zunjarrao &dev_attr_iface_header_digest.attr,
6393e0f65b3SHarish Zunjarrao &dev_attr_iface_data_digest.attr,
6403e0f65b3SHarish Zunjarrao &dev_attr_iface_immediate_data.attr,
6413e0f65b3SHarish Zunjarrao &dev_attr_iface_initial_r2t.attr,
6423e0f65b3SHarish Zunjarrao &dev_attr_iface_data_seq_in_order.attr,
6433e0f65b3SHarish Zunjarrao &dev_attr_iface_data_pdu_in_order.attr,
6443e0f65b3SHarish Zunjarrao &dev_attr_iface_erl.attr,
6453e0f65b3SHarish Zunjarrao &dev_attr_iface_max_recv_dlength.attr,
6463e0f65b3SHarish Zunjarrao &dev_attr_iface_first_burst_len.attr,
6473e0f65b3SHarish Zunjarrao &dev_attr_iface_max_outstanding_r2t.attr,
6483e0f65b3SHarish Zunjarrao &dev_attr_iface_max_burst_len.attr,
6493e0f65b3SHarish Zunjarrao &dev_attr_iface_chap_auth.attr,
6503e0f65b3SHarish Zunjarrao &dev_attr_iface_bidi_chap.attr,
6513e0f65b3SHarish Zunjarrao &dev_attr_iface_discovery_auth_optional.attr,
6523e0f65b3SHarish Zunjarrao &dev_attr_iface_discovery_logout.attr,
6533e0f65b3SHarish Zunjarrao &dev_attr_iface_strict_login_comp_en.attr,
6543e0f65b3SHarish Zunjarrao &dev_attr_iface_initiator_name.attr,
6553e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_dns_address_en.attr,
6563e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_slp_da_info_en.attr,
6573e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_tos_en.attr,
6583e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_tos.attr,
6593e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_grat_arp_en.attr,
6603e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_alt_client_id_en.attr,
6613e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_alt_client_id.attr,
6623e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_req_vendor_id_en.attr,
6633e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_use_vendor_id_en.attr,
6643e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_vendor_id.attr,
6653e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_dhcp_learn_iqn_en.attr,
6663e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_fragment_disable.attr,
6673e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_incoming_forwarding_en.attr,
6683e0f65b3SHarish Zunjarrao &dev_attr_ipv4_iface_ttl.attr,
6693e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_link_local_state.attr,
6703e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_router_state.attr,
6713e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_grat_neighbor_adv_en.attr,
6723e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_mld_en.attr,
6733e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_flow_label.attr,
6743e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_traffic_class.attr,
6753e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_hop_limit.attr,
6763e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_nd_reachable_tmo.attr,
6773e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_nd_rexmit_time.attr,
6783e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_nd_stale_tmo.attr,
6793e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_dup_addr_detect_cnt.attr,
6803e0f65b3SHarish Zunjarrao &dev_attr_ipv6_iface_router_adv_link_mtu.attr,
6818d07913dSMike Christie NULL,
6828d07913dSMike Christie };
6838d07913dSMike Christie
6848d07913dSMike Christie static struct attribute_group iscsi_iface_group = {
6858d07913dSMike Christie .attrs = iscsi_iface_attrs,
6868d07913dSMike Christie .is_visible = iscsi_iface_attr_is_visible,
6878d07913dSMike Christie };
6888d07913dSMike Christie
6893e0f65b3SHarish Zunjarrao /* convert iscsi_ipaddress_state values to ascii string name */
6903e0f65b3SHarish Zunjarrao static const struct {
6913e0f65b3SHarish Zunjarrao enum iscsi_ipaddress_state value;
6923e0f65b3SHarish Zunjarrao char *name;
6933e0f65b3SHarish Zunjarrao } iscsi_ipaddress_state_names[] = {
6943e0f65b3SHarish Zunjarrao {ISCSI_IPDDRESS_STATE_UNCONFIGURED, "Unconfigured" },
6953e0f65b3SHarish Zunjarrao {ISCSI_IPDDRESS_STATE_ACQUIRING, "Acquiring" },
6963e0f65b3SHarish Zunjarrao {ISCSI_IPDDRESS_STATE_TENTATIVE, "Tentative" },
6973e0f65b3SHarish Zunjarrao {ISCSI_IPDDRESS_STATE_VALID, "Valid" },
6983e0f65b3SHarish Zunjarrao {ISCSI_IPDDRESS_STATE_DISABLING, "Disabling" },
6993e0f65b3SHarish Zunjarrao {ISCSI_IPDDRESS_STATE_INVALID, "Invalid" },
7003e0f65b3SHarish Zunjarrao {ISCSI_IPDDRESS_STATE_DEPRECATED, "Deprecated" },
7013e0f65b3SHarish Zunjarrao };
7023e0f65b3SHarish Zunjarrao
iscsi_get_ipaddress_state_name(enum iscsi_ipaddress_state port_state)7033e0f65b3SHarish Zunjarrao char *iscsi_get_ipaddress_state_name(enum iscsi_ipaddress_state port_state)
7043e0f65b3SHarish Zunjarrao {
7053e0f65b3SHarish Zunjarrao int i;
7063e0f65b3SHarish Zunjarrao char *state = NULL;
7073e0f65b3SHarish Zunjarrao
7083e0f65b3SHarish Zunjarrao for (i = 0; i < ARRAY_SIZE(iscsi_ipaddress_state_names); i++) {
7093e0f65b3SHarish Zunjarrao if (iscsi_ipaddress_state_names[i].value == port_state) {
7103e0f65b3SHarish Zunjarrao state = iscsi_ipaddress_state_names[i].name;
7113e0f65b3SHarish Zunjarrao break;
7123e0f65b3SHarish Zunjarrao }
7133e0f65b3SHarish Zunjarrao }
7143e0f65b3SHarish Zunjarrao return state;
7153e0f65b3SHarish Zunjarrao }
7163e0f65b3SHarish Zunjarrao EXPORT_SYMBOL_GPL(iscsi_get_ipaddress_state_name);
7173e0f65b3SHarish Zunjarrao
7183e0f65b3SHarish Zunjarrao /* convert iscsi_router_state values to ascii string name */
7193e0f65b3SHarish Zunjarrao static const struct {
7203e0f65b3SHarish Zunjarrao enum iscsi_router_state value;
7213e0f65b3SHarish Zunjarrao char *name;
7223e0f65b3SHarish Zunjarrao } iscsi_router_state_names[] = {
7233e0f65b3SHarish Zunjarrao {ISCSI_ROUTER_STATE_UNKNOWN, "Unknown" },
7243e0f65b3SHarish Zunjarrao {ISCSI_ROUTER_STATE_ADVERTISED, "Advertised" },
7253e0f65b3SHarish Zunjarrao {ISCSI_ROUTER_STATE_MANUAL, "Manual" },
7263e0f65b3SHarish Zunjarrao {ISCSI_ROUTER_STATE_STALE, "Stale" },
7273e0f65b3SHarish Zunjarrao };
7283e0f65b3SHarish Zunjarrao
iscsi_get_router_state_name(enum iscsi_router_state router_state)7293e0f65b3SHarish Zunjarrao char *iscsi_get_router_state_name(enum iscsi_router_state router_state)
7303e0f65b3SHarish Zunjarrao {
7313e0f65b3SHarish Zunjarrao int i;
7323e0f65b3SHarish Zunjarrao char *state = NULL;
7333e0f65b3SHarish Zunjarrao
7343e0f65b3SHarish Zunjarrao for (i = 0; i < ARRAY_SIZE(iscsi_router_state_names); i++) {
7353e0f65b3SHarish Zunjarrao if (iscsi_router_state_names[i].value == router_state) {
7363e0f65b3SHarish Zunjarrao state = iscsi_router_state_names[i].name;
7373e0f65b3SHarish Zunjarrao break;
7383e0f65b3SHarish Zunjarrao }
7393e0f65b3SHarish Zunjarrao }
7403e0f65b3SHarish Zunjarrao return state;
7413e0f65b3SHarish Zunjarrao }
7423e0f65b3SHarish Zunjarrao EXPORT_SYMBOL_GPL(iscsi_get_router_state_name);
7433e0f65b3SHarish Zunjarrao
7448d07913dSMike Christie struct iscsi_iface *
iscsi_create_iface(struct Scsi_Host * shost,struct iscsi_transport * transport,uint32_t iface_type,uint32_t iface_num,int dd_size)7458d07913dSMike Christie iscsi_create_iface(struct Scsi_Host *shost, struct iscsi_transport *transport,
7468d07913dSMike Christie uint32_t iface_type, uint32_t iface_num, int dd_size)
7478d07913dSMike Christie {
7488d07913dSMike Christie struct iscsi_iface *iface;
7498d07913dSMike Christie int err;
7508d07913dSMike Christie
7518d07913dSMike Christie iface = kzalloc(sizeof(*iface) + dd_size, GFP_KERNEL);
7528d07913dSMike Christie if (!iface)
7538d07913dSMike Christie return NULL;
7548d07913dSMike Christie
7558d07913dSMike Christie iface->transport = transport;
7568d07913dSMike Christie iface->iface_type = iface_type;
7578d07913dSMike Christie iface->iface_num = iface_num;
7588d07913dSMike Christie iface->dev.release = iscsi_iface_release;
7598d07913dSMike Christie iface->dev.class = &iscsi_iface_class;
7608d07913dSMike Christie /* parent reference released in iscsi_iface_release */
7618d07913dSMike Christie iface->dev.parent = get_device(&shost->shost_gendev);
7628d07913dSMike Christie if (iface_type == ISCSI_IFACE_TYPE_IPV4)
7638d07913dSMike Christie dev_set_name(&iface->dev, "ipv4-iface-%u-%u", shost->host_no,
7648d07913dSMike Christie iface_num);
7658d07913dSMike Christie else
7668d07913dSMike Christie dev_set_name(&iface->dev, "ipv6-iface-%u-%u", shost->host_no,
7678d07913dSMike Christie iface_num);
7688d07913dSMike Christie
7698d07913dSMike Christie err = device_register(&iface->dev);
7708d07913dSMike Christie if (err)
771f014165fSZhou Guanghui goto put_dev;
7728d07913dSMike Christie
7738d07913dSMike Christie err = sysfs_create_group(&iface->dev.kobj, &iscsi_iface_group);
7748d07913dSMike Christie if (err)
7758d07913dSMike Christie goto unreg_iface;
7768d07913dSMike Christie
7778d07913dSMike Christie if (dd_size)
7788d07913dSMike Christie iface->dd_data = &iface[1];
7798d07913dSMike Christie return iface;
7808d07913dSMike Christie
7818d07913dSMike Christie unreg_iface:
7828d07913dSMike Christie device_unregister(&iface->dev);
7838d07913dSMike Christie return NULL;
7848d07913dSMike Christie
785f014165fSZhou Guanghui put_dev:
786f014165fSZhou Guanghui put_device(&iface->dev);
7878d07913dSMike Christie return NULL;
7888d07913dSMike Christie }
7898d07913dSMike Christie EXPORT_SYMBOL_GPL(iscsi_create_iface);
7908d07913dSMike Christie
iscsi_destroy_iface(struct iscsi_iface * iface)7918d07913dSMike Christie void iscsi_destroy_iface(struct iscsi_iface *iface)
7928d07913dSMike Christie {
7938d07913dSMike Christie sysfs_remove_group(&iface->dev.kobj, &iscsi_iface_group);
7948d07913dSMike Christie device_unregister(&iface->dev);
7958d07913dSMike Christie }
7968d07913dSMike Christie EXPORT_SYMBOL_GPL(iscsi_destroy_iface);
7978d07913dSMike Christie
79890eeb01aSMike Christie /*
799c6a4bb2eSAdheer Chandravanshi * Interface to display flash node params to sysfs
800c6a4bb2eSAdheer Chandravanshi */
801c6a4bb2eSAdheer Chandravanshi
802c6a4bb2eSAdheer Chandravanshi #define ISCSI_FLASHNODE_ATTR(_prefix, _name, _mode, _show, _store) \
803c6a4bb2eSAdheer Chandravanshi struct device_attribute dev_attr_##_prefix##_##_name = \
804c6a4bb2eSAdheer Chandravanshi __ATTR(_name, _mode, _show, _store)
805c6a4bb2eSAdheer Chandravanshi
806c6a4bb2eSAdheer Chandravanshi /* flash node session attrs show */
807c6a4bb2eSAdheer Chandravanshi #define iscsi_flashnode_sess_attr_show(type, name, param) \
808c6a4bb2eSAdheer Chandravanshi static ssize_t \
809c6a4bb2eSAdheer Chandravanshi show_##type##_##name(struct device *dev, struct device_attribute *attr, \
810c6a4bb2eSAdheer Chandravanshi char *buf) \
811c6a4bb2eSAdheer Chandravanshi { \
812c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess = \
813c6a4bb2eSAdheer Chandravanshi iscsi_dev_to_flash_session(dev);\
814c6a4bb2eSAdheer Chandravanshi struct iscsi_transport *t = fnode_sess->transport; \
815c6a4bb2eSAdheer Chandravanshi return t->get_flashnode_param(fnode_sess, param, buf); \
816c6a4bb2eSAdheer Chandravanshi } \
817c6a4bb2eSAdheer Chandravanshi
818c6a4bb2eSAdheer Chandravanshi
819c6a4bb2eSAdheer Chandravanshi #define iscsi_flashnode_sess_attr(type, name, param) \
820c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr_show(type, name, param) \
821c6a4bb2eSAdheer Chandravanshi static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO, \
822c6a4bb2eSAdheer Chandravanshi show_##type##_##name, NULL);
823c6a4bb2eSAdheer Chandravanshi
824c6a4bb2eSAdheer Chandravanshi /* Flash node session attributes */
825c6a4bb2eSAdheer Chandravanshi
826c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, auto_snd_tgt_disable,
827c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE);
828c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, discovery_session,
829c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_DISCOVERY_SESS);
830c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, portal_type, ISCSI_FLASHNODE_PORTAL_TYPE);
831c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, entry_enable, ISCSI_FLASHNODE_ENTRY_EN);
832c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, immediate_data, ISCSI_FLASHNODE_IMM_DATA_EN);
833c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, initial_r2t, ISCSI_FLASHNODE_INITIAL_R2T_EN);
834c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, data_seq_in_order,
835c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_DATASEQ_INORDER);
836c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, data_pdu_in_order,
837c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_PDU_INORDER);
838c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, chap_auth, ISCSI_FLASHNODE_CHAP_AUTH_EN);
839c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, discovery_logout,
840c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN);
841c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, bidi_chap, ISCSI_FLASHNODE_BIDI_CHAP_EN);
842c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, discovery_auth_optional,
843c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL);
844c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, erl, ISCSI_FLASHNODE_ERL);
845c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, first_burst_len, ISCSI_FLASHNODE_FIRST_BURST);
846c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, def_time2wait, ISCSI_FLASHNODE_DEF_TIME2WAIT);
847c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, def_time2retain,
848c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_DEF_TIME2RETAIN);
849c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, max_outstanding_r2t, ISCSI_FLASHNODE_MAX_R2T);
850c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, isid, ISCSI_FLASHNODE_ISID);
851c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, tsid, ISCSI_FLASHNODE_TSID);
852c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, max_burst_len, ISCSI_FLASHNODE_MAX_BURST);
853c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, def_taskmgmt_tmo,
854c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_DEF_TASKMGMT_TMO);
855c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, targetalias, ISCSI_FLASHNODE_ALIAS);
856c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, targetname, ISCSI_FLASHNODE_NAME);
857c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, tpgt, ISCSI_FLASHNODE_TPGT);
858c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, discovery_parent_idx,
859c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX);
860c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, discovery_parent_type,
861c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE);
862c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, chap_in_idx, ISCSI_FLASHNODE_CHAP_IN_IDX);
863c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, chap_out_idx, ISCSI_FLASHNODE_CHAP_OUT_IDX);
864c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, username, ISCSI_FLASHNODE_USERNAME);
865c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, username_in, ISCSI_FLASHNODE_USERNAME_IN);
866c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, password, ISCSI_FLASHNODE_PASSWORD);
867c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, password_in, ISCSI_FLASHNODE_PASSWORD_IN);
868c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_sess_attr(fnode, is_boot_target, ISCSI_FLASHNODE_IS_BOOT_TGT);
869c6a4bb2eSAdheer Chandravanshi
870c6a4bb2eSAdheer Chandravanshi static struct attribute *iscsi_flashnode_sess_attrs[] = {
871c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_auto_snd_tgt_disable.attr,
872c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_discovery_session.attr,
873c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_portal_type.attr,
874c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_entry_enable.attr,
875c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_immediate_data.attr,
876c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_initial_r2t.attr,
877c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_data_seq_in_order.attr,
878c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_data_pdu_in_order.attr,
879c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_chap_auth.attr,
880c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_discovery_logout.attr,
881c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_bidi_chap.attr,
882c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_discovery_auth_optional.attr,
883c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_erl.attr,
884c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_first_burst_len.attr,
885c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_def_time2wait.attr,
886c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_def_time2retain.attr,
887c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_max_outstanding_r2t.attr,
888c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_isid.attr,
889c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_tsid.attr,
890c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_max_burst_len.attr,
891c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_def_taskmgmt_tmo.attr,
892c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_targetalias.attr,
893c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_targetname.attr,
894c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_tpgt.attr,
895c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_discovery_parent_idx.attr,
896c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_discovery_parent_type.attr,
897c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_chap_in_idx.attr,
898c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_chap_out_idx.attr,
899c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_username.attr,
900c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_username_in.attr,
901c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_password.attr,
902c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_password_in.attr,
903c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_is_boot_target.attr,
904c6a4bb2eSAdheer Chandravanshi NULL,
905c6a4bb2eSAdheer Chandravanshi };
906c6a4bb2eSAdheer Chandravanshi
iscsi_flashnode_sess_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)907c6a4bb2eSAdheer Chandravanshi static umode_t iscsi_flashnode_sess_attr_is_visible(struct kobject *kobj,
908c6a4bb2eSAdheer Chandravanshi struct attribute *attr,
909c6a4bb2eSAdheer Chandravanshi int i)
910c6a4bb2eSAdheer Chandravanshi {
911c6a4bb2eSAdheer Chandravanshi struct device *dev = container_of(kobj, struct device, kobj);
912c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess =
913c6a4bb2eSAdheer Chandravanshi iscsi_dev_to_flash_session(dev);
914c6a4bb2eSAdheer Chandravanshi struct iscsi_transport *t = fnode_sess->transport;
915c6a4bb2eSAdheer Chandravanshi int param;
916c6a4bb2eSAdheer Chandravanshi
917c6a4bb2eSAdheer Chandravanshi if (attr == &dev_attr_fnode_auto_snd_tgt_disable.attr) {
918c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_AUTO_SND_TGT_DISABLE;
919c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_discovery_session.attr) {
920c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DISCOVERY_SESS;
921c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_portal_type.attr) {
922c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_PORTAL_TYPE;
923c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_entry_enable.attr) {
924c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_ENTRY_EN;
925c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_immediate_data.attr) {
926c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_IMM_DATA_EN;
927c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_initial_r2t.attr) {
928c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_INITIAL_R2T_EN;
929c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_data_seq_in_order.attr) {
930c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DATASEQ_INORDER;
931c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_data_pdu_in_order.attr) {
932c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_PDU_INORDER;
933c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_chap_auth.attr) {
934c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_CHAP_AUTH_EN;
935c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_discovery_logout.attr) {
936c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DISCOVERY_LOGOUT_EN;
937c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_bidi_chap.attr) {
938c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_BIDI_CHAP_EN;
939c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_discovery_auth_optional.attr) {
940c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DISCOVERY_AUTH_OPTIONAL;
941c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_erl.attr) {
942c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_ERL;
943c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_first_burst_len.attr) {
944c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_FIRST_BURST;
945c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_def_time2wait.attr) {
946c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DEF_TIME2WAIT;
947c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_def_time2retain.attr) {
948c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DEF_TIME2RETAIN;
949c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_max_outstanding_r2t.attr) {
950c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_MAX_R2T;
951c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_isid.attr) {
952c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_ISID;
953c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_tsid.attr) {
954c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_TSID;
955c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_max_burst_len.attr) {
956c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_MAX_BURST;
957c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_def_taskmgmt_tmo.attr) {
958c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DEF_TASKMGMT_TMO;
959c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_targetalias.attr) {
960c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_ALIAS;
961c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_targetname.attr) {
962c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_NAME;
963c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_tpgt.attr) {
964c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_TPGT;
965c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_discovery_parent_idx.attr) {
966c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DISCOVERY_PARENT_IDX;
967c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_discovery_parent_type.attr) {
968c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DISCOVERY_PARENT_TYPE;
969c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_chap_in_idx.attr) {
970c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_CHAP_IN_IDX;
971c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_chap_out_idx.attr) {
972c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_CHAP_OUT_IDX;
973c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_username.attr) {
974c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_USERNAME;
975c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_username_in.attr) {
976c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_USERNAME_IN;
977c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_password.attr) {
978c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_PASSWORD;
979c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_password_in.attr) {
980c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_PASSWORD_IN;
981c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_is_boot_target.attr) {
982c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_IS_BOOT_TGT;
983c6a4bb2eSAdheer Chandravanshi } else {
984c6a4bb2eSAdheer Chandravanshi WARN_ONCE(1, "Invalid flashnode session attr");
985c6a4bb2eSAdheer Chandravanshi return 0;
986c6a4bb2eSAdheer Chandravanshi }
987c6a4bb2eSAdheer Chandravanshi
988c6a4bb2eSAdheer Chandravanshi return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
989c6a4bb2eSAdheer Chandravanshi }
990c6a4bb2eSAdheer Chandravanshi
991c6a4bb2eSAdheer Chandravanshi static struct attribute_group iscsi_flashnode_sess_attr_group = {
992c6a4bb2eSAdheer Chandravanshi .attrs = iscsi_flashnode_sess_attrs,
993c6a4bb2eSAdheer Chandravanshi .is_visible = iscsi_flashnode_sess_attr_is_visible,
994c6a4bb2eSAdheer Chandravanshi };
995c6a4bb2eSAdheer Chandravanshi
996c6a4bb2eSAdheer Chandravanshi static const struct attribute_group *iscsi_flashnode_sess_attr_groups[] = {
997c6a4bb2eSAdheer Chandravanshi &iscsi_flashnode_sess_attr_group,
998c6a4bb2eSAdheer Chandravanshi NULL,
999c6a4bb2eSAdheer Chandravanshi };
1000c6a4bb2eSAdheer Chandravanshi
iscsi_flashnode_sess_release(struct device * dev)1001c6a4bb2eSAdheer Chandravanshi static void iscsi_flashnode_sess_release(struct device *dev)
1002c6a4bb2eSAdheer Chandravanshi {
1003c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess =
1004c6a4bb2eSAdheer Chandravanshi iscsi_dev_to_flash_session(dev);
1005c6a4bb2eSAdheer Chandravanshi
1006c6a4bb2eSAdheer Chandravanshi kfree(fnode_sess->targetname);
1007c6a4bb2eSAdheer Chandravanshi kfree(fnode_sess->targetalias);
1008c6a4bb2eSAdheer Chandravanshi kfree(fnode_sess->portal_type);
1009c6a4bb2eSAdheer Chandravanshi kfree(fnode_sess);
1010c6a4bb2eSAdheer Chandravanshi }
1011c6a4bb2eSAdheer Chandravanshi
10127988faf5SBhumika Goyal static const struct device_type iscsi_flashnode_sess_dev_type = {
1013c6a4bb2eSAdheer Chandravanshi .name = "iscsi_flashnode_sess_dev_type",
1014c6a4bb2eSAdheer Chandravanshi .groups = iscsi_flashnode_sess_attr_groups,
1015c6a4bb2eSAdheer Chandravanshi .release = iscsi_flashnode_sess_release,
1016c6a4bb2eSAdheer Chandravanshi };
1017c6a4bb2eSAdheer Chandravanshi
1018c6a4bb2eSAdheer Chandravanshi /* flash node connection attrs show */
1019c6a4bb2eSAdheer Chandravanshi #define iscsi_flashnode_conn_attr_show(type, name, param) \
1020c6a4bb2eSAdheer Chandravanshi static ssize_t \
1021c6a4bb2eSAdheer Chandravanshi show_##type##_##name(struct device *dev, struct device_attribute *attr, \
1022c6a4bb2eSAdheer Chandravanshi char *buf) \
1023c6a4bb2eSAdheer Chandravanshi { \
1024c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);\
1025c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess = \
1026c6a4bb2eSAdheer Chandravanshi iscsi_flash_conn_to_flash_session(fnode_conn);\
1027c6a4bb2eSAdheer Chandravanshi struct iscsi_transport *t = fnode_conn->transport; \
1028c6a4bb2eSAdheer Chandravanshi return t->get_flashnode_param(fnode_sess, param, buf); \
1029c6a4bb2eSAdheer Chandravanshi } \
1030c6a4bb2eSAdheer Chandravanshi
1031c6a4bb2eSAdheer Chandravanshi
1032c6a4bb2eSAdheer Chandravanshi #define iscsi_flashnode_conn_attr(type, name, param) \
1033c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr_show(type, name, param) \
1034c6a4bb2eSAdheer Chandravanshi static ISCSI_FLASHNODE_ATTR(type, name, S_IRUGO, \
1035c6a4bb2eSAdheer Chandravanshi show_##type##_##name, NULL);
1036c6a4bb2eSAdheer Chandravanshi
1037c6a4bb2eSAdheer Chandravanshi /* Flash node connection attributes */
1038c6a4bb2eSAdheer Chandravanshi
1039c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, is_fw_assigned_ipv6,
1040c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6);
1041c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, header_digest, ISCSI_FLASHNODE_HDR_DGST_EN);
1042c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, data_digest, ISCSI_FLASHNODE_DATA_DGST_EN);
1043c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, snack_req, ISCSI_FLASHNODE_SNACK_REQ_EN);
1044c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, tcp_timestamp_stat,
1045c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT);
1046c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, tcp_nagle_disable,
1047c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_TCP_NAGLE_DISABLE);
1048c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, tcp_wsf_disable,
1049c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_TCP_WSF_DISABLE);
1050c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, tcp_timer_scale,
1051c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_TCP_TIMER_SCALE);
1052c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, tcp_timestamp_enable,
1053c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_TCP_TIMESTAMP_EN);
1054c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, fragment_disable,
1055c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_IP_FRAG_DISABLE);
1056c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, keepalive_tmo, ISCSI_FLASHNODE_KEEPALIVE_TMO);
1057c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, port, ISCSI_FLASHNODE_PORT);
1058c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, ipaddress, ISCSI_FLASHNODE_IPADDR);
1059c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, max_recv_dlength,
1060c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_MAX_RECV_DLENGTH);
1061c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, max_xmit_dlength,
1062c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_MAX_XMIT_DLENGTH);
1063c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, local_port, ISCSI_FLASHNODE_LOCAL_PORT);
1064c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, ipv4_tos, ISCSI_FLASHNODE_IPV4_TOS);
1065c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, ipv6_traffic_class, ISCSI_FLASHNODE_IPV6_TC);
1066c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, ipv6_flow_label,
1067c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_IPV6_FLOW_LABEL);
1068c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, redirect_ipaddr,
1069c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_REDIRECT_IPADDR);
1070c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, max_segment_size,
1071c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_MAX_SEGMENT_SIZE);
1072c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, link_local_ipv6,
1073c6a4bb2eSAdheer Chandravanshi ISCSI_FLASHNODE_LINK_LOCAL_IPV6);
1074c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, tcp_xmit_wsf, ISCSI_FLASHNODE_TCP_XMIT_WSF);
1075c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, tcp_recv_wsf, ISCSI_FLASHNODE_TCP_RECV_WSF);
1076c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, statsn, ISCSI_FLASHNODE_STATSN);
1077c6a4bb2eSAdheer Chandravanshi iscsi_flashnode_conn_attr(fnode, exp_statsn, ISCSI_FLASHNODE_EXP_STATSN);
1078c6a4bb2eSAdheer Chandravanshi
1079c6a4bb2eSAdheer Chandravanshi static struct attribute *iscsi_flashnode_conn_attrs[] = {
1080c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_is_fw_assigned_ipv6.attr,
1081c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_header_digest.attr,
1082c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_data_digest.attr,
1083c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_snack_req.attr,
1084c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_tcp_timestamp_stat.attr,
1085c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_tcp_nagle_disable.attr,
1086c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_tcp_wsf_disable.attr,
1087c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_tcp_timer_scale.attr,
1088c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_tcp_timestamp_enable.attr,
1089c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_fragment_disable.attr,
1090c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_max_recv_dlength.attr,
1091c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_max_xmit_dlength.attr,
1092c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_keepalive_tmo.attr,
1093c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_port.attr,
1094c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_ipaddress.attr,
1095c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_redirect_ipaddr.attr,
1096c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_max_segment_size.attr,
1097c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_local_port.attr,
1098c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_ipv4_tos.attr,
1099c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_ipv6_traffic_class.attr,
1100c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_ipv6_flow_label.attr,
1101c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_link_local_ipv6.attr,
1102c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_tcp_xmit_wsf.attr,
1103c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_tcp_recv_wsf.attr,
1104c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_statsn.attr,
1105c6a4bb2eSAdheer Chandravanshi &dev_attr_fnode_exp_statsn.attr,
1106c6a4bb2eSAdheer Chandravanshi NULL,
1107c6a4bb2eSAdheer Chandravanshi };
1108c6a4bb2eSAdheer Chandravanshi
iscsi_flashnode_conn_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)1109c6a4bb2eSAdheer Chandravanshi static umode_t iscsi_flashnode_conn_attr_is_visible(struct kobject *kobj,
1110c6a4bb2eSAdheer Chandravanshi struct attribute *attr,
1111c6a4bb2eSAdheer Chandravanshi int i)
1112c6a4bb2eSAdheer Chandravanshi {
1113c6a4bb2eSAdheer Chandravanshi struct device *dev = container_of(kobj, struct device, kobj);
1114c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
1115c6a4bb2eSAdheer Chandravanshi struct iscsi_transport *t = fnode_conn->transport;
1116c6a4bb2eSAdheer Chandravanshi int param;
1117c6a4bb2eSAdheer Chandravanshi
1118c6a4bb2eSAdheer Chandravanshi if (attr == &dev_attr_fnode_is_fw_assigned_ipv6.attr) {
1119c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_IS_FW_ASSIGNED_IPV6;
1120c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_header_digest.attr) {
1121c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_HDR_DGST_EN;
1122c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_data_digest.attr) {
1123c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_DATA_DGST_EN;
1124c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_snack_req.attr) {
1125c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_SNACK_REQ_EN;
1126c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_tcp_timestamp_stat.attr) {
1127c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_TCP_TIMESTAMP_STAT;
1128c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_tcp_nagle_disable.attr) {
1129c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_TCP_NAGLE_DISABLE;
1130c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_tcp_wsf_disable.attr) {
1131c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_TCP_WSF_DISABLE;
1132c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_tcp_timer_scale.attr) {
1133c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_TCP_TIMER_SCALE;
1134c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_tcp_timestamp_enable.attr) {
1135c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_TCP_TIMESTAMP_EN;
1136c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_fragment_disable.attr) {
1137c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_IP_FRAG_DISABLE;
1138c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_max_recv_dlength.attr) {
1139c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_MAX_RECV_DLENGTH;
1140c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_max_xmit_dlength.attr) {
1141c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_MAX_XMIT_DLENGTH;
1142c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_keepalive_tmo.attr) {
1143c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_KEEPALIVE_TMO;
1144c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_port.attr) {
1145c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_PORT;
1146c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_ipaddress.attr) {
1147c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_IPADDR;
1148c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_redirect_ipaddr.attr) {
1149c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_REDIRECT_IPADDR;
1150c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_max_segment_size.attr) {
1151c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_MAX_SEGMENT_SIZE;
1152c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_local_port.attr) {
1153c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_LOCAL_PORT;
1154c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_ipv4_tos.attr) {
1155c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_IPV4_TOS;
1156c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_ipv6_traffic_class.attr) {
1157c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_IPV6_TC;
1158c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_ipv6_flow_label.attr) {
1159c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_IPV6_FLOW_LABEL;
1160c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_link_local_ipv6.attr) {
1161c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_LINK_LOCAL_IPV6;
1162c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_tcp_xmit_wsf.attr) {
1163c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_TCP_XMIT_WSF;
1164c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_tcp_recv_wsf.attr) {
1165c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_TCP_RECV_WSF;
1166c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_statsn.attr) {
1167c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_STATSN;
1168c6a4bb2eSAdheer Chandravanshi } else if (attr == &dev_attr_fnode_exp_statsn.attr) {
1169c6a4bb2eSAdheer Chandravanshi param = ISCSI_FLASHNODE_EXP_STATSN;
1170c6a4bb2eSAdheer Chandravanshi } else {
1171c6a4bb2eSAdheer Chandravanshi WARN_ONCE(1, "Invalid flashnode connection attr");
1172c6a4bb2eSAdheer Chandravanshi return 0;
1173c6a4bb2eSAdheer Chandravanshi }
1174c6a4bb2eSAdheer Chandravanshi
1175c6a4bb2eSAdheer Chandravanshi return t->attr_is_visible(ISCSI_FLASHNODE_PARAM, param);
1176c6a4bb2eSAdheer Chandravanshi }
1177c6a4bb2eSAdheer Chandravanshi
1178c6a4bb2eSAdheer Chandravanshi static struct attribute_group iscsi_flashnode_conn_attr_group = {
1179c6a4bb2eSAdheer Chandravanshi .attrs = iscsi_flashnode_conn_attrs,
1180c6a4bb2eSAdheer Chandravanshi .is_visible = iscsi_flashnode_conn_attr_is_visible,
1181c6a4bb2eSAdheer Chandravanshi };
1182c6a4bb2eSAdheer Chandravanshi
1183c6a4bb2eSAdheer Chandravanshi static const struct attribute_group *iscsi_flashnode_conn_attr_groups[] = {
1184c6a4bb2eSAdheer Chandravanshi &iscsi_flashnode_conn_attr_group,
1185c6a4bb2eSAdheer Chandravanshi NULL,
1186c6a4bb2eSAdheer Chandravanshi };
1187c6a4bb2eSAdheer Chandravanshi
iscsi_flashnode_conn_release(struct device * dev)1188c6a4bb2eSAdheer Chandravanshi static void iscsi_flashnode_conn_release(struct device *dev)
1189c6a4bb2eSAdheer Chandravanshi {
1190c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_conn *fnode_conn = iscsi_dev_to_flash_conn(dev);
1191c6a4bb2eSAdheer Chandravanshi
1192c6a4bb2eSAdheer Chandravanshi kfree(fnode_conn->ipaddress);
1193c6a4bb2eSAdheer Chandravanshi kfree(fnode_conn->redirect_ipaddr);
1194c6a4bb2eSAdheer Chandravanshi kfree(fnode_conn->link_local_ipv6_addr);
1195c6a4bb2eSAdheer Chandravanshi kfree(fnode_conn);
1196c6a4bb2eSAdheer Chandravanshi }
1197c6a4bb2eSAdheer Chandravanshi
11987988faf5SBhumika Goyal static const struct device_type iscsi_flashnode_conn_dev_type = {
1199c6a4bb2eSAdheer Chandravanshi .name = "iscsi_flashnode_conn_dev_type",
1200c6a4bb2eSAdheer Chandravanshi .groups = iscsi_flashnode_conn_attr_groups,
1201c6a4bb2eSAdheer Chandravanshi .release = iscsi_flashnode_conn_release,
1202c6a4bb2eSAdheer Chandravanshi };
1203c6a4bb2eSAdheer Chandravanshi
12044c1340afSBart Van Assche static struct bus_type iscsi_flashnode_bus;
1205c6a4bb2eSAdheer Chandravanshi
iscsi_flashnode_bus_match(struct device * dev,struct device_driver * drv)1206c6a4bb2eSAdheer Chandravanshi int iscsi_flashnode_bus_match(struct device *dev,
1207c6a4bb2eSAdheer Chandravanshi struct device_driver *drv)
1208c6a4bb2eSAdheer Chandravanshi {
1209c6a4bb2eSAdheer Chandravanshi if (dev->bus == &iscsi_flashnode_bus)
1210c6a4bb2eSAdheer Chandravanshi return 1;
1211c6a4bb2eSAdheer Chandravanshi return 0;
1212c6a4bb2eSAdheer Chandravanshi }
1213c6a4bb2eSAdheer Chandravanshi EXPORT_SYMBOL_GPL(iscsi_flashnode_bus_match);
1214c6a4bb2eSAdheer Chandravanshi
12154c1340afSBart Van Assche static struct bus_type iscsi_flashnode_bus = {
1216c6a4bb2eSAdheer Chandravanshi .name = "iscsi_flashnode",
1217c6a4bb2eSAdheer Chandravanshi .match = &iscsi_flashnode_bus_match,
1218c6a4bb2eSAdheer Chandravanshi };
1219c6a4bb2eSAdheer Chandravanshi
1220c6a4bb2eSAdheer Chandravanshi /**
1221c6a4bb2eSAdheer Chandravanshi * iscsi_create_flashnode_sess - Add flashnode session entry in sysfs
1222c6a4bb2eSAdheer Chandravanshi * @shost: pointer to host data
1223c6a4bb2eSAdheer Chandravanshi * @index: index of flashnode to add in sysfs
1224c6a4bb2eSAdheer Chandravanshi * @transport: pointer to transport data
1225c6a4bb2eSAdheer Chandravanshi * @dd_size: total size to allocate
1226c6a4bb2eSAdheer Chandravanshi *
1227c6a4bb2eSAdheer Chandravanshi * Adds a sysfs entry for the flashnode session attributes
1228c6a4bb2eSAdheer Chandravanshi *
1229c6a4bb2eSAdheer Chandravanshi * Returns:
1230e227867fSMasanari Iida * pointer to allocated flashnode sess on success
1231c6a4bb2eSAdheer Chandravanshi * %NULL on failure
1232c6a4bb2eSAdheer Chandravanshi */
1233c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *
iscsi_create_flashnode_sess(struct Scsi_Host * shost,int index,struct iscsi_transport * transport,int dd_size)1234c6a4bb2eSAdheer Chandravanshi iscsi_create_flashnode_sess(struct Scsi_Host *shost, int index,
1235c6a4bb2eSAdheer Chandravanshi struct iscsi_transport *transport,
1236c6a4bb2eSAdheer Chandravanshi int dd_size)
1237c6a4bb2eSAdheer Chandravanshi {
1238c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess;
1239c6a4bb2eSAdheer Chandravanshi int err;
1240c6a4bb2eSAdheer Chandravanshi
1241c6a4bb2eSAdheer Chandravanshi fnode_sess = kzalloc(sizeof(*fnode_sess) + dd_size, GFP_KERNEL);
1242c6a4bb2eSAdheer Chandravanshi if (!fnode_sess)
1243c6a4bb2eSAdheer Chandravanshi return NULL;
1244c6a4bb2eSAdheer Chandravanshi
1245c6a4bb2eSAdheer Chandravanshi fnode_sess->transport = transport;
1246c6a4bb2eSAdheer Chandravanshi fnode_sess->target_id = index;
1247c6a4bb2eSAdheer Chandravanshi fnode_sess->dev.type = &iscsi_flashnode_sess_dev_type;
1248c6a4bb2eSAdheer Chandravanshi fnode_sess->dev.bus = &iscsi_flashnode_bus;
1249c6a4bb2eSAdheer Chandravanshi fnode_sess->dev.parent = &shost->shost_gendev;
1250c6a4bb2eSAdheer Chandravanshi dev_set_name(&fnode_sess->dev, "flashnode_sess-%u:%u",
1251c6a4bb2eSAdheer Chandravanshi shost->host_no, index);
1252c6a4bb2eSAdheer Chandravanshi
1253c6a4bb2eSAdheer Chandravanshi err = device_register(&fnode_sess->dev);
1254c6a4bb2eSAdheer Chandravanshi if (err)
1255f014165fSZhou Guanghui goto put_dev;
1256c6a4bb2eSAdheer Chandravanshi
1257c6a4bb2eSAdheer Chandravanshi if (dd_size)
1258c6a4bb2eSAdheer Chandravanshi fnode_sess->dd_data = &fnode_sess[1];
1259c6a4bb2eSAdheer Chandravanshi
1260c6a4bb2eSAdheer Chandravanshi return fnode_sess;
1261c6a4bb2eSAdheer Chandravanshi
1262f014165fSZhou Guanghui put_dev:
1263f014165fSZhou Guanghui put_device(&fnode_sess->dev);
1264c6a4bb2eSAdheer Chandravanshi return NULL;
1265c6a4bb2eSAdheer Chandravanshi }
1266c6a4bb2eSAdheer Chandravanshi EXPORT_SYMBOL_GPL(iscsi_create_flashnode_sess);
1267c6a4bb2eSAdheer Chandravanshi
1268c6a4bb2eSAdheer Chandravanshi /**
1269c6a4bb2eSAdheer Chandravanshi * iscsi_create_flashnode_conn - Add flashnode conn entry in sysfs
1270c6a4bb2eSAdheer Chandravanshi * @shost: pointer to host data
1271c6a4bb2eSAdheer Chandravanshi * @fnode_sess: pointer to the parent flashnode session entry
1272c6a4bb2eSAdheer Chandravanshi * @transport: pointer to transport data
1273c6a4bb2eSAdheer Chandravanshi * @dd_size: total size to allocate
1274c6a4bb2eSAdheer Chandravanshi *
1275c6a4bb2eSAdheer Chandravanshi * Adds a sysfs entry for the flashnode connection attributes
1276c6a4bb2eSAdheer Chandravanshi *
1277c6a4bb2eSAdheer Chandravanshi * Returns:
1278c6a4bb2eSAdheer Chandravanshi * pointer to allocated flashnode conn on success
1279c6a4bb2eSAdheer Chandravanshi * %NULL on failure
1280c6a4bb2eSAdheer Chandravanshi */
1281c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_conn *
iscsi_create_flashnode_conn(struct Scsi_Host * shost,struct iscsi_bus_flash_session * fnode_sess,struct iscsi_transport * transport,int dd_size)1282c6a4bb2eSAdheer Chandravanshi iscsi_create_flashnode_conn(struct Scsi_Host *shost,
1283c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess,
1284c6a4bb2eSAdheer Chandravanshi struct iscsi_transport *transport,
1285c6a4bb2eSAdheer Chandravanshi int dd_size)
1286c6a4bb2eSAdheer Chandravanshi {
1287c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_conn *fnode_conn;
1288c6a4bb2eSAdheer Chandravanshi int err;
1289c6a4bb2eSAdheer Chandravanshi
1290c6a4bb2eSAdheer Chandravanshi fnode_conn = kzalloc(sizeof(*fnode_conn) + dd_size, GFP_KERNEL);
1291c6a4bb2eSAdheer Chandravanshi if (!fnode_conn)
1292c6a4bb2eSAdheer Chandravanshi return NULL;
1293c6a4bb2eSAdheer Chandravanshi
1294c6a4bb2eSAdheer Chandravanshi fnode_conn->transport = transport;
1295c6a4bb2eSAdheer Chandravanshi fnode_conn->dev.type = &iscsi_flashnode_conn_dev_type;
1296c6a4bb2eSAdheer Chandravanshi fnode_conn->dev.bus = &iscsi_flashnode_bus;
1297c6a4bb2eSAdheer Chandravanshi fnode_conn->dev.parent = &fnode_sess->dev;
1298c6a4bb2eSAdheer Chandravanshi dev_set_name(&fnode_conn->dev, "flashnode_conn-%u:%u:0",
1299c6a4bb2eSAdheer Chandravanshi shost->host_no, fnode_sess->target_id);
1300c6a4bb2eSAdheer Chandravanshi
1301c6a4bb2eSAdheer Chandravanshi err = device_register(&fnode_conn->dev);
1302c6a4bb2eSAdheer Chandravanshi if (err)
1303f014165fSZhou Guanghui goto put_dev;
1304c6a4bb2eSAdheer Chandravanshi
1305c6a4bb2eSAdheer Chandravanshi if (dd_size)
1306c6a4bb2eSAdheer Chandravanshi fnode_conn->dd_data = &fnode_conn[1];
1307c6a4bb2eSAdheer Chandravanshi
1308c6a4bb2eSAdheer Chandravanshi return fnode_conn;
1309c6a4bb2eSAdheer Chandravanshi
1310f014165fSZhou Guanghui put_dev:
1311f014165fSZhou Guanghui put_device(&fnode_conn->dev);
1312c6a4bb2eSAdheer Chandravanshi return NULL;
1313c6a4bb2eSAdheer Chandravanshi }
1314c6a4bb2eSAdheer Chandravanshi EXPORT_SYMBOL_GPL(iscsi_create_flashnode_conn);
1315c6a4bb2eSAdheer Chandravanshi
1316c6a4bb2eSAdheer Chandravanshi /**
1317c6a4bb2eSAdheer Chandravanshi * iscsi_is_flashnode_conn_dev - verify passed device is to be flashnode conn
1318c6a4bb2eSAdheer Chandravanshi * @dev: device to verify
1319c6a4bb2eSAdheer Chandravanshi * @data: pointer to data containing value to use for verification
1320c6a4bb2eSAdheer Chandravanshi *
1321c6a4bb2eSAdheer Chandravanshi * Verifies if the passed device is flashnode conn device
1322c6a4bb2eSAdheer Chandravanshi *
1323c6a4bb2eSAdheer Chandravanshi * Returns:
1324c6a4bb2eSAdheer Chandravanshi * 1 on success
1325c6a4bb2eSAdheer Chandravanshi * 0 on failure
1326c6a4bb2eSAdheer Chandravanshi */
iscsi_is_flashnode_conn_dev(struct device * dev,void * data)13277a15fdfaSBart Van Assche static int iscsi_is_flashnode_conn_dev(struct device *dev, void *data)
1328c6a4bb2eSAdheer Chandravanshi {
1329c6a4bb2eSAdheer Chandravanshi return dev->bus == &iscsi_flashnode_bus;
1330c6a4bb2eSAdheer Chandravanshi }
1331c6a4bb2eSAdheer Chandravanshi
iscsi_destroy_flashnode_conn(struct iscsi_bus_flash_conn * fnode_conn)1332c6a4bb2eSAdheer Chandravanshi static int iscsi_destroy_flashnode_conn(struct iscsi_bus_flash_conn *fnode_conn)
1333c6a4bb2eSAdheer Chandravanshi {
1334c6a4bb2eSAdheer Chandravanshi device_unregister(&fnode_conn->dev);
1335c6a4bb2eSAdheer Chandravanshi return 0;
1336c6a4bb2eSAdheer Chandravanshi }
1337c6a4bb2eSAdheer Chandravanshi
flashnode_match_index(struct device * dev,void * data)1338c6a4bb2eSAdheer Chandravanshi static int flashnode_match_index(struct device *dev, void *data)
1339c6a4bb2eSAdheer Chandravanshi {
1340c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess = NULL;
1341c6a4bb2eSAdheer Chandravanshi int ret = 0;
1342c6a4bb2eSAdheer Chandravanshi
1343c6a4bb2eSAdheer Chandravanshi if (!iscsi_flashnode_bus_match(dev, NULL))
1344c6a4bb2eSAdheer Chandravanshi goto exit_match_index;
1345c6a4bb2eSAdheer Chandravanshi
1346c6a4bb2eSAdheer Chandravanshi fnode_sess = iscsi_dev_to_flash_session(dev);
1347c6a4bb2eSAdheer Chandravanshi ret = (fnode_sess->target_id == *((int *)data)) ? 1 : 0;
1348c6a4bb2eSAdheer Chandravanshi
1349c6a4bb2eSAdheer Chandravanshi exit_match_index:
1350c6a4bb2eSAdheer Chandravanshi return ret;
1351c6a4bb2eSAdheer Chandravanshi }
1352c6a4bb2eSAdheer Chandravanshi
1353c6a4bb2eSAdheer Chandravanshi /**
1354c6a4bb2eSAdheer Chandravanshi * iscsi_get_flashnode_by_index -finds flashnode session entry by index
1355c6a4bb2eSAdheer Chandravanshi * @shost: pointer to host data
13568526cb11SMike Christie * @idx: index to match
1357c6a4bb2eSAdheer Chandravanshi *
1358c6a4bb2eSAdheer Chandravanshi * Finds the flashnode session object for the passed index
1359c6a4bb2eSAdheer Chandravanshi *
1360c6a4bb2eSAdheer Chandravanshi * Returns:
1361c6a4bb2eSAdheer Chandravanshi * pointer to found flashnode session object on success
1362c6a4bb2eSAdheer Chandravanshi * %NULL on failure
1363c6a4bb2eSAdheer Chandravanshi */
1364c6a4bb2eSAdheer Chandravanshi static struct iscsi_bus_flash_session *
iscsi_get_flashnode_by_index(struct Scsi_Host * shost,uint32_t idx)13658526cb11SMike Christie iscsi_get_flashnode_by_index(struct Scsi_Host *shost, uint32_t idx)
1366c6a4bb2eSAdheer Chandravanshi {
1367c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess = NULL;
1368c6a4bb2eSAdheer Chandravanshi struct device *dev;
1369c6a4bb2eSAdheer Chandravanshi
13708526cb11SMike Christie dev = device_find_child(&shost->shost_gendev, &idx,
13718526cb11SMike Christie flashnode_match_index);
1372c6a4bb2eSAdheer Chandravanshi if (dev)
1373c6a4bb2eSAdheer Chandravanshi fnode_sess = iscsi_dev_to_flash_session(dev);
1374c6a4bb2eSAdheer Chandravanshi
1375c6a4bb2eSAdheer Chandravanshi return fnode_sess;
1376c6a4bb2eSAdheer Chandravanshi }
1377c6a4bb2eSAdheer Chandravanshi
1378c6a4bb2eSAdheer Chandravanshi /**
1379c6a4bb2eSAdheer Chandravanshi * iscsi_find_flashnode_sess - finds flashnode session entry
1380c6a4bb2eSAdheer Chandravanshi * @shost: pointer to host data
1381c6a4bb2eSAdheer Chandravanshi * @data: pointer to data containing value to use for comparison
1382c6a4bb2eSAdheer Chandravanshi * @fn: function pointer that does actual comparison
1383c6a4bb2eSAdheer Chandravanshi *
1384c6a4bb2eSAdheer Chandravanshi * Finds the flashnode session object comparing the data passed using logic
1385c6a4bb2eSAdheer Chandravanshi * defined in passed function pointer
1386c6a4bb2eSAdheer Chandravanshi *
1387c6a4bb2eSAdheer Chandravanshi * Returns:
1388c6a4bb2eSAdheer Chandravanshi * pointer to found flashnode session device object on success
1389c6a4bb2eSAdheer Chandravanshi * %NULL on failure
1390c6a4bb2eSAdheer Chandravanshi */
1391c6a4bb2eSAdheer Chandravanshi struct device *
iscsi_find_flashnode_sess(struct Scsi_Host * shost,void * data,int (* fn)(struct device * dev,void * data))1392c6a4bb2eSAdheer Chandravanshi iscsi_find_flashnode_sess(struct Scsi_Host *shost, void *data,
1393c6a4bb2eSAdheer Chandravanshi int (*fn)(struct device *dev, void *data))
1394c6a4bb2eSAdheer Chandravanshi {
13958526cb11SMike Christie return device_find_child(&shost->shost_gendev, data, fn);
1396c6a4bb2eSAdheer Chandravanshi }
1397c6a4bb2eSAdheer Chandravanshi EXPORT_SYMBOL_GPL(iscsi_find_flashnode_sess);
1398c6a4bb2eSAdheer Chandravanshi
1399c6a4bb2eSAdheer Chandravanshi /**
1400c6a4bb2eSAdheer Chandravanshi * iscsi_find_flashnode_conn - finds flashnode connection entry
1401c6a4bb2eSAdheer Chandravanshi * @fnode_sess: pointer to parent flashnode session entry
1402c6a4bb2eSAdheer Chandravanshi *
1403c6a4bb2eSAdheer Chandravanshi * Finds the flashnode connection object comparing the data passed using logic
1404c6a4bb2eSAdheer Chandravanshi * defined in passed function pointer
1405c6a4bb2eSAdheer Chandravanshi *
1406c6a4bb2eSAdheer Chandravanshi * Returns:
1407c6a4bb2eSAdheer Chandravanshi * pointer to found flashnode connection device object on success
1408c6a4bb2eSAdheer Chandravanshi * %NULL on failure
1409c6a4bb2eSAdheer Chandravanshi */
1410c6a4bb2eSAdheer Chandravanshi struct device *
iscsi_find_flashnode_conn(struct iscsi_bus_flash_session * fnode_sess)14118526cb11SMike Christie iscsi_find_flashnode_conn(struct iscsi_bus_flash_session *fnode_sess)
1412c6a4bb2eSAdheer Chandravanshi {
14138526cb11SMike Christie return device_find_child(&fnode_sess->dev, NULL,
14148526cb11SMike Christie iscsi_is_flashnode_conn_dev);
1415c6a4bb2eSAdheer Chandravanshi }
1416c6a4bb2eSAdheer Chandravanshi EXPORT_SYMBOL_GPL(iscsi_find_flashnode_conn);
1417c6a4bb2eSAdheer Chandravanshi
iscsi_iter_destroy_flashnode_conn_fn(struct device * dev,void * data)1418c6a4bb2eSAdheer Chandravanshi static int iscsi_iter_destroy_flashnode_conn_fn(struct device *dev, void *data)
1419c6a4bb2eSAdheer Chandravanshi {
1420c6a4bb2eSAdheer Chandravanshi if (!iscsi_is_flashnode_conn_dev(dev, NULL))
1421c6a4bb2eSAdheer Chandravanshi return 0;
1422c6a4bb2eSAdheer Chandravanshi
1423c6a4bb2eSAdheer Chandravanshi return iscsi_destroy_flashnode_conn(iscsi_dev_to_flash_conn(dev));
1424c6a4bb2eSAdheer Chandravanshi }
1425c6a4bb2eSAdheer Chandravanshi
1426c6a4bb2eSAdheer Chandravanshi /**
1427e227867fSMasanari Iida * iscsi_destroy_flashnode_sess - destroy flashnode session entry
1428c6a4bb2eSAdheer Chandravanshi * @fnode_sess: pointer to flashnode session entry to be destroyed
1429c6a4bb2eSAdheer Chandravanshi *
1430c6a4bb2eSAdheer Chandravanshi * Deletes the flashnode session entry and all children flashnode connection
1431c6a4bb2eSAdheer Chandravanshi * entries from sysfs
1432c6a4bb2eSAdheer Chandravanshi */
iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session * fnode_sess)1433c6a4bb2eSAdheer Chandravanshi void iscsi_destroy_flashnode_sess(struct iscsi_bus_flash_session *fnode_sess)
1434c6a4bb2eSAdheer Chandravanshi {
1435c6a4bb2eSAdheer Chandravanshi int err;
1436c6a4bb2eSAdheer Chandravanshi
1437c6a4bb2eSAdheer Chandravanshi err = device_for_each_child(&fnode_sess->dev, NULL,
1438c6a4bb2eSAdheer Chandravanshi iscsi_iter_destroy_flashnode_conn_fn);
1439c6a4bb2eSAdheer Chandravanshi if (err)
1440c6a4bb2eSAdheer Chandravanshi pr_err("Could not delete all connections for %s. Error %d.\n",
1441c6a4bb2eSAdheer Chandravanshi fnode_sess->dev.kobj.name, err);
1442c6a4bb2eSAdheer Chandravanshi
1443c6a4bb2eSAdheer Chandravanshi device_unregister(&fnode_sess->dev);
1444c6a4bb2eSAdheer Chandravanshi }
1445c6a4bb2eSAdheer Chandravanshi EXPORT_SYMBOL_GPL(iscsi_destroy_flashnode_sess);
1446c6a4bb2eSAdheer Chandravanshi
iscsi_iter_destroy_flashnode_fn(struct device * dev,void * data)1447c6a4bb2eSAdheer Chandravanshi static int iscsi_iter_destroy_flashnode_fn(struct device *dev, void *data)
1448c6a4bb2eSAdheer Chandravanshi {
1449c6a4bb2eSAdheer Chandravanshi if (!iscsi_flashnode_bus_match(dev, NULL))
1450c6a4bb2eSAdheer Chandravanshi return 0;
1451c6a4bb2eSAdheer Chandravanshi
1452c6a4bb2eSAdheer Chandravanshi iscsi_destroy_flashnode_sess(iscsi_dev_to_flash_session(dev));
1453c6a4bb2eSAdheer Chandravanshi return 0;
1454c6a4bb2eSAdheer Chandravanshi }
1455c6a4bb2eSAdheer Chandravanshi
1456c6a4bb2eSAdheer Chandravanshi /**
1457e227867fSMasanari Iida * iscsi_destroy_all_flashnode - destroy all flashnode session entries
1458c6a4bb2eSAdheer Chandravanshi * @shost: pointer to host data
1459c6a4bb2eSAdheer Chandravanshi *
1460c6a4bb2eSAdheer Chandravanshi * Destroys all the flashnode session entries and all corresponding children
1461c6a4bb2eSAdheer Chandravanshi * flashnode connection entries from sysfs
1462c6a4bb2eSAdheer Chandravanshi */
iscsi_destroy_all_flashnode(struct Scsi_Host * shost)1463c6a4bb2eSAdheer Chandravanshi void iscsi_destroy_all_flashnode(struct Scsi_Host *shost)
1464c6a4bb2eSAdheer Chandravanshi {
1465c6a4bb2eSAdheer Chandravanshi device_for_each_child(&shost->shost_gendev, NULL,
1466c6a4bb2eSAdheer Chandravanshi iscsi_iter_destroy_flashnode_fn);
1467c6a4bb2eSAdheer Chandravanshi }
1468c6a4bb2eSAdheer Chandravanshi EXPORT_SYMBOL_GPL(iscsi_destroy_all_flashnode);
1469c6a4bb2eSAdheer Chandravanshi
1470c6a4bb2eSAdheer Chandravanshi /*
147190eeb01aSMike Christie * BSG support
147290eeb01aSMike Christie */
147390eeb01aSMike Christie /**
147490eeb01aSMike Christie * iscsi_bsg_host_dispatch - Dispatch command to LLD.
147590eeb01aSMike Christie * @job: bsg job to be processed
147690eeb01aSMike Christie */
iscsi_bsg_host_dispatch(struct bsg_job * job)147790eeb01aSMike Christie static int iscsi_bsg_host_dispatch(struct bsg_job *job)
147890eeb01aSMike Christie {
147990eeb01aSMike Christie struct Scsi_Host *shost = iscsi_job_to_shost(job);
148090eeb01aSMike Christie struct iscsi_bsg_request *req = job->request;
148190eeb01aSMike Christie struct iscsi_bsg_reply *reply = job->reply;
148290eeb01aSMike Christie struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
148390eeb01aSMike Christie int cmdlen = sizeof(uint32_t); /* start with length of msgcode */
148490eeb01aSMike Christie int ret;
148590eeb01aSMike Christie
148690eeb01aSMike Christie /* check if we have the msgcode value at least */
148790eeb01aSMike Christie if (job->request_len < sizeof(uint32_t)) {
148890eeb01aSMike Christie ret = -ENOMSG;
148990eeb01aSMike Christie goto fail_host_msg;
149090eeb01aSMike Christie }
149190eeb01aSMike Christie
149290eeb01aSMike Christie /* Validate the host command */
149390eeb01aSMike Christie switch (req->msgcode) {
149490eeb01aSMike Christie case ISCSI_BSG_HST_VENDOR:
149590eeb01aSMike Christie cmdlen += sizeof(struct iscsi_bsg_host_vendor);
149690eeb01aSMike Christie if ((shost->hostt->vendor_id == 0L) ||
149790eeb01aSMike Christie (req->rqst_data.h_vendor.vendor_id !=
149890eeb01aSMike Christie shost->hostt->vendor_id)) {
149990eeb01aSMike Christie ret = -ESRCH;
150090eeb01aSMike Christie goto fail_host_msg;
150190eeb01aSMike Christie }
150290eeb01aSMike Christie break;
150390eeb01aSMike Christie default:
150490eeb01aSMike Christie ret = -EBADR;
150590eeb01aSMike Christie goto fail_host_msg;
150690eeb01aSMike Christie }
150790eeb01aSMike Christie
150890eeb01aSMike Christie /* check if we really have all the request data needed */
150990eeb01aSMike Christie if (job->request_len < cmdlen) {
151090eeb01aSMike Christie ret = -ENOMSG;
151190eeb01aSMike Christie goto fail_host_msg;
151290eeb01aSMike Christie }
151390eeb01aSMike Christie
151490eeb01aSMike Christie ret = i->iscsi_transport->bsg_request(job);
151590eeb01aSMike Christie if (!ret)
151690eeb01aSMike Christie return 0;
151790eeb01aSMike Christie
151890eeb01aSMike Christie fail_host_msg:
151990eeb01aSMike Christie /* return the errno failure code as the only status */
152090eeb01aSMike Christie BUG_ON(job->reply_len < sizeof(uint32_t));
152190eeb01aSMike Christie reply->reply_payload_rcv_len = 0;
152290eeb01aSMike Christie reply->result = ret;
152390eeb01aSMike Christie job->reply_len = sizeof(uint32_t);
152490eeb01aSMike Christie bsg_job_done(job, ret, 0);
152590eeb01aSMike Christie return 0;
152690eeb01aSMike Christie }
152790eeb01aSMike Christie
152890eeb01aSMike Christie /**
152990eeb01aSMike Christie * iscsi_bsg_host_add - Create and add the bsg hooks to receive requests
153090eeb01aSMike Christie * @shost: shost for iscsi_host
1531eae627e4SMarcos Paulo de Souza * @ihost: iscsi_cls_host adding the structures to
153290eeb01aSMike Christie */
153390eeb01aSMike Christie static int
iscsi_bsg_host_add(struct Scsi_Host * shost,struct iscsi_cls_host * ihost)153490eeb01aSMike Christie iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
153590eeb01aSMike Christie {
153690eeb01aSMike Christie struct device *dev = &shost->shost_gendev;
153790eeb01aSMike Christie struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
153890eeb01aSMike Christie struct request_queue *q;
153990eeb01aSMike Christie char bsg_name[20];
154090eeb01aSMike Christie
154190eeb01aSMike Christie if (!i->iscsi_transport->bsg_request)
154290eeb01aSMike Christie return -ENOTSUPP;
154390eeb01aSMike Christie
154490eeb01aSMike Christie snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
1545aae3b069SJens Axboe q = bsg_setup_queue(dev, bsg_name, iscsi_bsg_host_dispatch, NULL, 0);
15468ae94eb6SChristoph Hellwig if (IS_ERR(q)) {
154790eeb01aSMike Christie shost_printk(KERN_ERR, shost, "bsg interface failed to "
154890eeb01aSMike Christie "initialize - no request queue\n");
15498ae94eb6SChristoph Hellwig return PTR_ERR(q);
155090eeb01aSMike Christie }
15518ae94eb6SChristoph Hellwig __scsi_init_queue(shost, q);
155290eeb01aSMike Christie
155390eeb01aSMike Christie ihost->bsg_q = q;
155490eeb01aSMike Christie return 0;
155590eeb01aSMike Christie }
155690eeb01aSMike Christie
iscsi_setup_host(struct transport_container * tc,struct device * dev,struct device * cdev)155730a6c652SMike Christie static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
1558ee959b00STony Jones struct device *cdev)
155930a6c652SMike Christie {
156030a6c652SMike Christie struct Scsi_Host *shost = dev_to_shost(dev);
156132c6e1b9SMike Christie struct iscsi_cls_host *ihost = shost->shost_data;
156230a6c652SMike Christie
156330a6c652SMike Christie memset(ihost, 0, sizeof(*ihost));
15647970634bSMike Christie mutex_init(&ihost->mutex);
156590eeb01aSMike Christie
156690eeb01aSMike Christie iscsi_bsg_host_add(shost, ihost);
156790eeb01aSMike Christie /* ignore any bsg add error - we just can't do sgio */
156890eeb01aSMike Christie
156990eeb01aSMike Christie return 0;
157090eeb01aSMike Christie }
157190eeb01aSMike Christie
iscsi_remove_host(struct transport_container * tc,struct device * dev,struct device * cdev)157290eeb01aSMike Christie static int iscsi_remove_host(struct transport_container *tc,
157390eeb01aSMike Christie struct device *dev, struct device *cdev)
157490eeb01aSMike Christie {
157590eeb01aSMike Christie struct Scsi_Host *shost = dev_to_shost(dev);
157690eeb01aSMike Christie struct iscsi_cls_host *ihost = shost->shost_data;
157790eeb01aSMike Christie
15785e28b8d8SJens Axboe bsg_remove_queue(ihost->bsg_q);
157930a6c652SMike Christie return 0;
158030a6c652SMike Christie }
158130a6c652SMike Christie
158230a6c652SMike Christie static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
158330a6c652SMike Christie "iscsi_host",
158430a6c652SMike Christie iscsi_setup_host,
158590eeb01aSMike Christie iscsi_remove_host,
158630a6c652SMike Christie NULL);
158730a6c652SMike Christie
15880896b752SAlex Aizman static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
15890896b752SAlex Aizman "iscsi_session",
15901da177e4SLinus Torvalds NULL,
15911da177e4SLinus Torvalds NULL,
15921da177e4SLinus Torvalds NULL);
15931da177e4SLinus Torvalds
15940896b752SAlex Aizman static DECLARE_TRANSPORT_CLASS(iscsi_connection_class,
15950896b752SAlex Aizman "iscsi_connection",
15961da177e4SLinus Torvalds NULL,
15971da177e4SLinus Torvalds NULL,
15981da177e4SLinus Torvalds NULL);
15991da177e4SLinus Torvalds
16000896b752SAlex Aizman static struct sock *nls;
16010b950672SArjan van de Ven static DEFINE_MUTEX(rx_queue_mutex);
16021da177e4SLinus Torvalds
16037b7232f3SMike Christie static LIST_HEAD(sesslist);
16047b7232f3SMike Christie static DEFINE_SPINLOCK(sesslock);
16050896b752SAlex Aizman static LIST_HEAD(connlist);
16060ab71045SBharath Ravi static LIST_HEAD(connlist_err);
16070896b752SAlex Aizman static DEFINE_SPINLOCK(connlock);
16081da177e4SLinus Torvalds
iscsi_conn_get_sid(struct iscsi_cls_conn * conn)1609b5c7a12dSMike Christie static uint32_t iscsi_conn_get_sid(struct iscsi_cls_conn *conn)
1610b5c7a12dSMike Christie {
1611b5c7a12dSMike Christie struct iscsi_cls_session *sess = iscsi_dev_to_session(conn->dev.parent);
1612b5c7a12dSMike Christie return sess->sid;
1613b5c7a12dSMike Christie }
1614b5c7a12dSMike Christie
1615b5c7a12dSMike Christie /*
1616b5c7a12dSMike Christie * Returns the matching session to a given sid
1617b5c7a12dSMike Christie */
iscsi_session_lookup(uint32_t sid)1618b5c7a12dSMike Christie static struct iscsi_cls_session *iscsi_session_lookup(uint32_t sid)
16197b7232f3SMike Christie {
16207b7232f3SMike Christie unsigned long flags;
16217b7232f3SMike Christie struct iscsi_cls_session *sess;
16227b7232f3SMike Christie
16237b7232f3SMike Christie spin_lock_irqsave(&sesslock, flags);
16247b7232f3SMike Christie list_for_each_entry(sess, &sesslist, sess_list) {
1625b5c7a12dSMike Christie if (sess->sid == sid) {
16267b7232f3SMike Christie spin_unlock_irqrestore(&sesslock, flags);
16277b7232f3SMike Christie return sess;
16287b7232f3SMike Christie }
16297b7232f3SMike Christie }
16307b7232f3SMike Christie spin_unlock_irqrestore(&sesslock, flags);
16317b7232f3SMike Christie return NULL;
16327b7232f3SMike Christie }
16337b7232f3SMike Christie
1634b5c7a12dSMike Christie /*
1635b5c7a12dSMike Christie * Returns the matching connection to a given sid / cid tuple
1636b5c7a12dSMike Christie */
iscsi_conn_lookup(uint32_t sid,uint32_t cid)1637b5c7a12dSMike Christie static struct iscsi_cls_conn *iscsi_conn_lookup(uint32_t sid, uint32_t cid)
16387b7232f3SMike Christie {
16397b7232f3SMike Christie unsigned long flags;
16407b7232f3SMike Christie struct iscsi_cls_conn *conn;
16417b7232f3SMike Christie
16427b7232f3SMike Christie spin_lock_irqsave(&connlock, flags);
16437b7232f3SMike Christie list_for_each_entry(conn, &connlist, conn_list) {
1644b5c7a12dSMike Christie if ((conn->cid == cid) && (iscsi_conn_get_sid(conn) == sid)) {
16457b7232f3SMike Christie spin_unlock_irqrestore(&connlock, flags);
16467b7232f3SMike Christie return conn;
16477b7232f3SMike Christie }
16487b7232f3SMike Christie }
16497b7232f3SMike Christie spin_unlock_irqrestore(&connlock, flags);
16507b7232f3SMike Christie return NULL;
16517b7232f3SMike Christie }
16527b7232f3SMike Christie
16537b8631b5SMike Christie /*
16547b8631b5SMike Christie * The following functions can be used by LLDs that allocate
16557b8631b5SMike Christie * their own scsi_hosts or by software iscsi LLDs
16567b8631b5SMike Christie */
16576eabafbeSMike Christie static struct {
16586eabafbeSMike Christie int value;
16596eabafbeSMike Christie char *name;
16606eabafbeSMike Christie } iscsi_session_state_names[] = {
16616eabafbeSMike Christie { ISCSI_SESSION_LOGGED_IN, "LOGGED_IN" },
16626eabafbeSMike Christie { ISCSI_SESSION_FAILED, "FAILED" },
16636eabafbeSMike Christie { ISCSI_SESSION_FREE, "FREE" },
16646eabafbeSMike Christie };
16656eabafbeSMike Christie
iscsi_session_state_name(int state)16663b0f208aSAdrian Bunk static const char *iscsi_session_state_name(int state)
16676eabafbeSMike Christie {
16686eabafbeSMike Christie int i;
16696eabafbeSMike Christie char *name = NULL;
16706eabafbeSMike Christie
16716eabafbeSMike Christie for (i = 0; i < ARRAY_SIZE(iscsi_session_state_names); i++) {
16726eabafbeSMike Christie if (iscsi_session_state_names[i].value == state) {
16736eabafbeSMike Christie name = iscsi_session_state_names[i].name;
16746eabafbeSMike Christie break;
16756eabafbeSMike Christie }
16766eabafbeSMike Christie }
16776eabafbeSMike Christie return name;
16786eabafbeSMike Christie }
16796eabafbeSMike Christie
1680a3be19b9SWenchao Hao static char *iscsi_session_target_state_name[] = {
1681a3be19b9SWenchao Hao [ISCSI_SESSION_TARGET_UNBOUND] = "UNBOUND",
1682a3be19b9SWenchao Hao [ISCSI_SESSION_TARGET_ALLOCATED] = "ALLOCATED",
1683a3be19b9SWenchao Hao [ISCSI_SESSION_TARGET_SCANNED] = "SCANNED",
1684a3be19b9SWenchao Hao [ISCSI_SESSION_TARGET_UNBINDING] = "UNBINDING",
1685a3be19b9SWenchao Hao };
1686a3be19b9SWenchao Hao
iscsi_session_chkready(struct iscsi_cls_session * session)16876eabafbeSMike Christie int iscsi_session_chkready(struct iscsi_cls_session *session)
16886eabafbeSMike Christie {
16896eabafbeSMike Christie int err;
16906eabafbeSMike Christie
16916eabafbeSMike Christie switch (session->state) {
16926eabafbeSMike Christie case ISCSI_SESSION_LOGGED_IN:
16936eabafbeSMike Christie err = 0;
16946eabafbeSMike Christie break;
16956eabafbeSMike Christie case ISCSI_SESSION_FAILED:
16969a1a69a1SAndrew Vasquez err = DID_IMM_RETRY << 16;
16976eabafbeSMike Christie break;
16986eabafbeSMike Christie case ISCSI_SESSION_FREE:
169956d7fcfaSMike Christie err = DID_TRANSPORT_FAILFAST << 16;
17006eabafbeSMike Christie break;
17016eabafbeSMike Christie default:
17026eabafbeSMike Christie err = DID_NO_CONNECT << 16;
17036eabafbeSMike Christie break;
17046eabafbeSMike Christie }
17056eabafbeSMike Christie return err;
17066eabafbeSMike Christie }
17076eabafbeSMike Christie EXPORT_SYMBOL_GPL(iscsi_session_chkready);
17086eabafbeSMike Christie
iscsi_is_session_online(struct iscsi_cls_session * session)170917fa575eSManish Rangankar int iscsi_is_session_online(struct iscsi_cls_session *session)
171017fa575eSManish Rangankar {
171117fa575eSManish Rangankar unsigned long flags;
171217fa575eSManish Rangankar int ret = 0;
171317fa575eSManish Rangankar
171417fa575eSManish Rangankar spin_lock_irqsave(&session->lock, flags);
171517fa575eSManish Rangankar if (session->state == ISCSI_SESSION_LOGGED_IN)
171617fa575eSManish Rangankar ret = 1;
171717fa575eSManish Rangankar spin_unlock_irqrestore(&session->lock, flags);
171817fa575eSManish Rangankar return ret;
171917fa575eSManish Rangankar }
172017fa575eSManish Rangankar EXPORT_SYMBOL_GPL(iscsi_is_session_online);
172117fa575eSManish Rangankar
iscsi_session_release(struct device * dev)17227b8631b5SMike Christie static void iscsi_session_release(struct device *dev)
17237b8631b5SMike Christie {
17247b8631b5SMike Christie struct iscsi_cls_session *session = iscsi_dev_to_session(dev);
17257b8631b5SMike Christie struct Scsi_Host *shost;
17261da177e4SLinus Torvalds
17277b8631b5SMike Christie shost = iscsi_session_to_shost(session);
17287b8631b5SMike Christie scsi_host_put(shost);
1729632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completing session release\n");
17307b8631b5SMike Christie kfree(session);
17317b8631b5SMike Christie }
17321da177e4SLinus Torvalds
iscsi_is_session_dev(const struct device * dev)17336260a5d2SNilesh Javali int iscsi_is_session_dev(const struct device *dev)
17347b8631b5SMike Christie {
17357b8631b5SMike Christie return dev->release == iscsi_session_release;
17367b8631b5SMike Christie }
17376260a5d2SNilesh Javali EXPORT_SYMBOL_GPL(iscsi_is_session_dev);
17381da177e4SLinus Torvalds
iscsi_iter_session_fn(struct device * dev,void * data)1739a4804cd6SMike Christie static int iscsi_iter_session_fn(struct device *dev, void *data)
1740a4804cd6SMike Christie {
1741a4804cd6SMike Christie void (* fn) (struct iscsi_cls_session *) = data;
1742a4804cd6SMike Christie
1743a4804cd6SMike Christie if (!iscsi_is_session_dev(dev))
1744a4804cd6SMike Christie return 0;
1745a4804cd6SMike Christie fn(iscsi_dev_to_session(dev));
1746a4804cd6SMike Christie return 0;
1747a4804cd6SMike Christie }
1748a4804cd6SMike Christie
iscsi_host_for_each_session(struct Scsi_Host * shost,void (* fn)(struct iscsi_cls_session *))1749a4804cd6SMike Christie void iscsi_host_for_each_session(struct Scsi_Host *shost,
1750a4804cd6SMike Christie void (*fn)(struct iscsi_cls_session *))
1751a4804cd6SMike Christie {
1752a4804cd6SMike Christie device_for_each_child(&shost->shost_gendev, fn,
1753a4804cd6SMike Christie iscsi_iter_session_fn);
1754a4804cd6SMike Christie }
1755a4804cd6SMike Christie EXPORT_SYMBOL_GPL(iscsi_host_for_each_session);
1756a4804cd6SMike Christie
17577970634bSMike Christie struct iscsi_scan_data {
17587970634bSMike Christie unsigned int channel;
17597970634bSMike Christie unsigned int id;
17609cb78c16SHannes Reinecke u64 lun;
17611d645088SHannes Reinecke enum scsi_scan_mode rescan;
17627970634bSMike Christie };
17637970634bSMike Christie
iscsi_user_scan_session(struct device * dev,void * data)17647970634bSMike Christie static int iscsi_user_scan_session(struct device *dev, void *data)
17657970634bSMike Christie {
17667970634bSMike Christie struct iscsi_scan_data *scan_data = data;
17677970634bSMike Christie struct iscsi_cls_session *session;
17687970634bSMike Christie struct Scsi_Host *shost;
17697970634bSMike Christie struct iscsi_cls_host *ihost;
17707970634bSMike Christie unsigned long flags;
17717970634bSMike Christie unsigned int id;
17727970634bSMike Christie
17737970634bSMike Christie if (!iscsi_is_session_dev(dev))
17747970634bSMike Christie return 0;
17757970634bSMike Christie
17767970634bSMike Christie session = iscsi_dev_to_session(dev);
1777632248aaSMike Christie
1778632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Scanning session\n");
1779632248aaSMike Christie
17807970634bSMike Christie shost = iscsi_session_to_shost(session);
17817970634bSMike Christie ihost = shost->shost_data;
17827970634bSMike Christie
17837970634bSMike Christie mutex_lock(&ihost->mutex);
17847970634bSMike Christie spin_lock_irqsave(&session->lock, flags);
17857970634bSMike Christie if (session->state != ISCSI_SESSION_LOGGED_IN) {
17867970634bSMike Christie spin_unlock_irqrestore(&session->lock, flags);
1787632248aaSMike Christie goto user_scan_exit;
17887970634bSMike Christie }
17897970634bSMike Christie id = session->target_id;
17907970634bSMike Christie spin_unlock_irqrestore(&session->lock, flags);
17917970634bSMike Christie
17927970634bSMike Christie if (id != ISCSI_MAX_TARGET) {
17937970634bSMike Christie if ((scan_data->channel == SCAN_WILD_CARD ||
17947970634bSMike Christie scan_data->channel == 0) &&
17957970634bSMike Christie (scan_data->id == SCAN_WILD_CARD ||
1796a3be19b9SWenchao Hao scan_data->id == id)) {
17977970634bSMike Christie scsi_scan_target(&session->dev, 0, id,
17981d645088SHannes Reinecke scan_data->lun, scan_data->rescan);
1799a3be19b9SWenchao Hao spin_lock_irqsave(&session->lock, flags);
1800a3be19b9SWenchao Hao session->target_state = ISCSI_SESSION_TARGET_SCANNED;
1801a3be19b9SWenchao Hao spin_unlock_irqrestore(&session->lock, flags);
1802a3be19b9SWenchao Hao }
18037970634bSMike Christie }
1804632248aaSMike Christie
1805632248aaSMike Christie user_scan_exit:
18067970634bSMike Christie mutex_unlock(&ihost->mutex);
1807632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completed session scan\n");
18087970634bSMike Christie return 0;
18097970634bSMike Christie }
18107970634bSMike Christie
iscsi_user_scan(struct Scsi_Host * shost,uint channel,uint id,u64 lun)181130a6c652SMike Christie static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
18129cb78c16SHannes Reinecke uint id, u64 lun)
181330a6c652SMike Christie {
18147970634bSMike Christie struct iscsi_scan_data scan_data;
181530a6c652SMike Christie
18167970634bSMike Christie scan_data.channel = channel;
18177970634bSMike Christie scan_data.id = id;
18187970634bSMike Christie scan_data.lun = lun;
18191d645088SHannes Reinecke scan_data.rescan = SCSI_SCAN_MANUAL;
182030a6c652SMike Christie
18217970634bSMike Christie return device_for_each_child(&shost->shost_gendev, &scan_data,
18227970634bSMike Christie iscsi_user_scan_session);
182330a6c652SMike Christie }
182430a6c652SMike Christie
iscsi_scan_session(struct work_struct * work)1825bd976f62SMike Christie static void iscsi_scan_session(struct work_struct *work)
1826bd976f62SMike Christie {
1827bd976f62SMike Christie struct iscsi_cls_session *session =
1828bd976f62SMike Christie container_of(work, struct iscsi_cls_session, scan_work);
18297970634bSMike Christie struct iscsi_scan_data scan_data;
1830bd976f62SMike Christie
18317970634bSMike Christie scan_data.channel = 0;
18327970634bSMike Christie scan_data.id = SCAN_WILD_CARD;
18337970634bSMike Christie scan_data.lun = SCAN_WILD_CARD;
18341d645088SHannes Reinecke scan_data.rescan = SCSI_SCAN_RESCAN;
1835bd976f62SMike Christie
18367970634bSMike Christie iscsi_user_scan_session(&session->dev, &scan_data);
1837bd976f62SMike Christie }
1838bd976f62SMike Christie
1839c01be6dcSMike Christie /**
1840c01be6dcSMike Christie * iscsi_block_scsi_eh - block scsi eh until session state has transistioned
1841e6d4ef45SRandy Dunlap * @cmd: scsi cmd passed to scsi eh handler
1842c01be6dcSMike Christie *
1843c01be6dcSMike Christie * If the session is down this function will wait for the recovery
1844c01be6dcSMike Christie * timer to fire or for the session to be logged back in. If the
1845c01be6dcSMike Christie * recovery timer fires then FAST_IO_FAIL is returned. The caller
1846c01be6dcSMike Christie * should pass this error value to the scsi eh.
1847c01be6dcSMike Christie */
iscsi_block_scsi_eh(struct scsi_cmnd * cmd)1848c01be6dcSMike Christie int iscsi_block_scsi_eh(struct scsi_cmnd *cmd)
1849c01be6dcSMike Christie {
1850c01be6dcSMike Christie struct iscsi_cls_session *session =
1851c01be6dcSMike Christie starget_to_session(scsi_target(cmd->device));
1852c01be6dcSMike Christie unsigned long flags;
1853c01be6dcSMike Christie int ret = 0;
1854c01be6dcSMike Christie
1855c01be6dcSMike Christie spin_lock_irqsave(&session->lock, flags);
1856c01be6dcSMike Christie while (session->state != ISCSI_SESSION_LOGGED_IN) {
1857c01be6dcSMike Christie if (session->state == ISCSI_SESSION_FREE) {
1858c01be6dcSMike Christie ret = FAST_IO_FAIL;
1859c01be6dcSMike Christie break;
1860c01be6dcSMike Christie }
1861c01be6dcSMike Christie spin_unlock_irqrestore(&session->lock, flags);
1862c01be6dcSMike Christie msleep(1000);
1863c01be6dcSMike Christie spin_lock_irqsave(&session->lock, flags);
1864c01be6dcSMike Christie }
1865c01be6dcSMike Christie spin_unlock_irqrestore(&session->lock, flags);
1866c01be6dcSMike Christie return ret;
1867c01be6dcSMike Christie }
1868c01be6dcSMike Christie EXPORT_SYMBOL_GPL(iscsi_block_scsi_eh);
1869c01be6dcSMike Christie
session_recovery_timedout(struct work_struct * work)1870c4028958SDavid Howells static void session_recovery_timedout(struct work_struct *work)
187130a6c652SMike Christie {
1872c4028958SDavid Howells struct iscsi_cls_session *session =
1873c4028958SDavid Howells container_of(work, struct iscsi_cls_session,
1874c4028958SDavid Howells recovery_work.work);
18756eabafbeSMike Christie unsigned long flags;
187630a6c652SMike Christie
1877322d739dSMike Christie iscsi_cls_session_printk(KERN_INFO, session,
1878322d739dSMike Christie "session recovery timed out after %d secs\n",
1879322d739dSMike Christie session->recovery_tmo);
188030a6c652SMike Christie
18816eabafbeSMike Christie spin_lock_irqsave(&session->lock, flags);
18826eabafbeSMike Christie switch (session->state) {
18836eabafbeSMike Christie case ISCSI_SESSION_FAILED:
18846eabafbeSMike Christie session->state = ISCSI_SESSION_FREE;
18856eabafbeSMike Christie break;
18866eabafbeSMike Christie case ISCSI_SESSION_LOGGED_IN:
18876eabafbeSMike Christie case ISCSI_SESSION_FREE:
18886eabafbeSMike Christie /* we raced with the unblock's flush */
18896eabafbeSMike Christie spin_unlock_irqrestore(&session->lock, flags);
18906eabafbeSMike Christie return;
18916eabafbeSMike Christie }
18926eabafbeSMike Christie spin_unlock_irqrestore(&session->lock, flags);
18936eabafbeSMike Christie
1894632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Unblocking SCSI target\n");
18955d9fb5ccSMike Christie scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
1896632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking SCSI target\n");
1897a0c2f8b6SMike Christie
1898a0c2f8b6SMike Christie if (session->transport->session_recovery_timedout)
1899a0c2f8b6SMike Christie session->transport->session_recovery_timedout(session);
190030a6c652SMike Christie }
190130a6c652SMike Christie
__iscsi_unblock_session(struct work_struct * work)190245ab33b6SMike Christie static void __iscsi_unblock_session(struct work_struct *work)
190330a6c652SMike Christie {
190445ab33b6SMike Christie struct iscsi_cls_session *session =
190545ab33b6SMike Christie container_of(work, struct iscsi_cls_session,
190645ab33b6SMike Christie unblock_work);
19076eabafbeSMike Christie unsigned long flags;
19086eabafbeSMike Christie
1909632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Unblocking session\n");
19108dd3dff3SMike Christie
19118dd3dff3SMike Christie cancel_delayed_work_sync(&session->recovery_work);
19126eabafbeSMike Christie spin_lock_irqsave(&session->lock, flags);
19136eabafbeSMike Christie session->state = ISCSI_SESSION_LOGGED_IN;
19146eabafbeSMike Christie spin_unlock_irqrestore(&session->lock, flags);
191545ab33b6SMike Christie /* start IO */
19165d9fb5ccSMike Christie scsi_target_unblock(&session->dev, SDEV_RUNNING);
1917632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completed unblocking session\n");
19186eabafbeSMike Christie }
191945ab33b6SMike Christie
192045ab33b6SMike Christie /**
192145ab33b6SMike Christie * iscsi_unblock_session - set a session as logged in and start IO.
192245ab33b6SMike Christie * @session: iscsi session
192345ab33b6SMike Christie *
192445ab33b6SMike Christie * Mark a session as ready to accept IO.
192545ab33b6SMike Christie */
iscsi_unblock_session(struct iscsi_cls_session * session)192645ab33b6SMike Christie void iscsi_unblock_session(struct iscsi_cls_session *session)
192745ab33b6SMike Christie {
1928b07c348fSMike Christie if (!cancel_work_sync(&session->block_work))
1929b07c348fSMike Christie cancel_delayed_work_sync(&session->recovery_work);
19307ce9fc5eSMike Christie
19317cb6683cSMike Christie queue_work(session->workq, &session->unblock_work);
193245ab33b6SMike Christie /*
19331d726aa6SMike Christie * Blocking the session can be done from any context so we only
19341d726aa6SMike Christie * queue the block work. Make sure the unblock work has completed
19351d726aa6SMike Christie * because it flushes/cancels the other works and updates the state.
193645ab33b6SMike Christie */
19371d726aa6SMike Christie flush_work(&session->unblock_work);
193845ab33b6SMike Christie }
193930a6c652SMike Christie EXPORT_SYMBOL_GPL(iscsi_unblock_session);
194030a6c652SMike Christie
__iscsi_block_session(struct work_struct * work)194145ab33b6SMike Christie static void __iscsi_block_session(struct work_struct *work)
194230a6c652SMike Christie {
194345ab33b6SMike Christie struct iscsi_cls_session *session =
194445ab33b6SMike Christie container_of(work, struct iscsi_cls_session,
194545ab33b6SMike Christie block_work);
194631950192SMartin Wilck struct Scsi_Host *shost = iscsi_session_to_shost(session);
19476eabafbeSMike Christie unsigned long flags;
19486eabafbeSMike Christie
1949632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Blocking session\n");
19506eabafbeSMike Christie spin_lock_irqsave(&session->lock, flags);
19516eabafbeSMike Christie session->state = ISCSI_SESSION_FAILED;
19526eabafbeSMike Christie spin_unlock_irqrestore(&session->lock, flags);
195331950192SMartin Wilck scsi_block_targets(shost, &session->dev);
1954632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completed SCSI target blocking\n");
1955fdd46dcbSMike Christie if (session->recovery_tmo >= 0)
19567cb6683cSMike Christie queue_delayed_work(session->workq,
1957fdd46dcbSMike Christie &session->recovery_work,
195830a6c652SMike Christie session->recovery_tmo * HZ);
195930a6c652SMike Christie }
196045ab33b6SMike Christie
iscsi_block_session(struct iscsi_cls_session * session)196145ab33b6SMike Christie void iscsi_block_session(struct iscsi_cls_session *session)
196245ab33b6SMike Christie {
19637cb6683cSMike Christie queue_work(session->workq, &session->block_work);
196445ab33b6SMike Christie }
196530a6c652SMike Christie EXPORT_SYMBOL_GPL(iscsi_block_session);
196630a6c652SMike Christie
__iscsi_unbind_session(struct work_struct * work)196726974789SMike Christie static void __iscsi_unbind_session(struct work_struct *work)
196826974789SMike Christie {
196926974789SMike Christie struct iscsi_cls_session *session =
197026974789SMike Christie container_of(work, struct iscsi_cls_session,
197126974789SMike Christie unbind_work);
197226974789SMike Christie struct Scsi_Host *shost = iscsi_session_to_shost(session);
197332c6e1b9SMike Christie struct iscsi_cls_host *ihost = shost->shost_data;
19747970634bSMike Christie unsigned long flags;
19758d4a690cSMike Christie unsigned int target_id;
1976a3be19b9SWenchao Hao bool remove_target = true;
197726974789SMike Christie
1978632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Unbinding session\n");
1979632248aaSMike Christie
198026974789SMike Christie /* Prevent new scans and make sure scanning is not in progress */
198126974789SMike Christie mutex_lock(&ihost->mutex);
19827970634bSMike Christie spin_lock_irqsave(&session->lock, flags);
1983a3be19b9SWenchao Hao if (session->target_state == ISCSI_SESSION_TARGET_ALLOCATED) {
1984a3be19b9SWenchao Hao remove_target = false;
1985a3be19b9SWenchao Hao } else if (session->target_state != ISCSI_SESSION_TARGET_SCANNED) {
19867970634bSMike Christie spin_unlock_irqrestore(&session->lock, flags);
198726974789SMike Christie mutex_unlock(&ihost->mutex);
1988a3be19b9SWenchao Hao ISCSI_DBG_TRANS_SESSION(session,
1989a3be19b9SWenchao Hao "Skipping target unbinding: Session is unbound/unbinding.\n");
1990a3be19b9SWenchao Hao return;
199126974789SMike Christie }
19928d4a690cSMike Christie
1993a3be19b9SWenchao Hao session->target_state = ISCSI_SESSION_TARGET_UNBINDING;
19948d4a690cSMike Christie target_id = session->target_id;
19957970634bSMike Christie session->target_id = ISCSI_MAX_TARGET;
19967970634bSMike Christie spin_unlock_irqrestore(&session->lock, flags);
199726974789SMike Christie mutex_unlock(&ihost->mutex);
199826974789SMike Christie
1999a3be19b9SWenchao Hao if (remove_target)
2000e463f96bSMike Christie scsi_remove_target(&session->dev);
2001e463f96bSMike Christie
20028d4a690cSMike Christie if (session->ida_used)
20033fd3a52cSkeliu ida_free(&iscsi_sess_ida, target_id);
20048d4a690cSMike Christie
200526974789SMike Christie iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
2006632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completed target removal\n");
2007a3be19b9SWenchao Hao
2008a3be19b9SWenchao Hao spin_lock_irqsave(&session->lock, flags);
2009a3be19b9SWenchao Hao session->target_state = ISCSI_SESSION_TARGET_UNBOUND;
2010a3be19b9SWenchao Hao spin_unlock_irqrestore(&session->lock, flags);
201126974789SMike Christie }
201226974789SMike Christie
__iscsi_destroy_session(struct work_struct * work)2013cc6b32eeSFrank Mayhar static void __iscsi_destroy_session(struct work_struct *work)
2014cc6b32eeSFrank Mayhar {
2015cc6b32eeSFrank Mayhar struct iscsi_cls_session *session =
2016cc6b32eeSFrank Mayhar container_of(work, struct iscsi_cls_session, destroy_work);
2017cc6b32eeSFrank Mayhar
2018cc6b32eeSFrank Mayhar session->transport->destroy_session(session);
2019cc6b32eeSFrank Mayhar }
2020cc6b32eeSFrank Mayhar
20217b8631b5SMike Christie struct iscsi_cls_session *
iscsi_alloc_session(struct Scsi_Host * shost,struct iscsi_transport * transport,int dd_size)20225d91e209SMike Christie iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
20235d91e209SMike Christie int dd_size)
20247b8631b5SMike Christie {
20257b8631b5SMike Christie struct iscsi_cls_session *session;
20261da177e4SLinus Torvalds
20275d91e209SMike Christie session = kzalloc(sizeof(*session) + dd_size,
2028b5c7a12dSMike Christie GFP_KERNEL);
20297b8631b5SMike Christie if (!session)
2030f53a88daSMike Christie return NULL;
2031f53a88daSMike Christie
20327b8631b5SMike Christie session->transport = transport;
20330c70d84bSMike Christie session->creator = -1;
203430a6c652SMike Christie session->recovery_tmo = 120;
20359c8108a4SChris Leech session->recovery_tmo_sysfs_override = false;
20366eabafbeSMike Christie session->state = ISCSI_SESSION_FREE;
2037c4028958SDavid Howells INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
203830a6c652SMike Christie INIT_LIST_HEAD(&session->sess_list);
203945ab33b6SMike Christie INIT_WORK(&session->unblock_work, __iscsi_unblock_session);
204045ab33b6SMike Christie INIT_WORK(&session->block_work, __iscsi_block_session);
204126974789SMike Christie INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
2042bd976f62SMike Christie INIT_WORK(&session->scan_work, iscsi_scan_session);
2043cc6b32eeSFrank Mayhar INIT_WORK(&session->destroy_work, __iscsi_destroy_session);
20446eabafbeSMike Christie spin_lock_init(&session->lock);
20457b8631b5SMike Christie
20466a8a0d36SMike Christie /* this is released in the dev's release function */
20476a8a0d36SMike Christie scsi_host_get(shost);
20488434aa8bSMike Christie session->dev.parent = &shost->shost_gendev;
20498434aa8bSMike Christie session->dev.release = iscsi_session_release;
20508434aa8bSMike Christie device_initialize(&session->dev);
20515d91e209SMike Christie if (dd_size)
2052b5c7a12dSMike Christie session->dd_data = &session[1];
2053632248aaSMike Christie
2054632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completed session allocation\n");
20558434aa8bSMike Christie return session;
20568434aa8bSMike Christie }
20578434aa8bSMike Christie EXPORT_SYMBOL_GPL(iscsi_alloc_session);
20588434aa8bSMike Christie
iscsi_add_session(struct iscsi_cls_session * session,unsigned int target_id)20596a8a0d36SMike Christie int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)
20608434aa8bSMike Christie {
20615842ea36SMike Christie struct Scsi_Host *shost = iscsi_session_to_shost(session);
206226974789SMike Christie unsigned long flags;
20638d4a690cSMike Christie int id = 0;
20648434aa8bSMike Christie int err;
2065b5c7a12dSMike Christie
206641be1444SMike Christie session->sid = atomic_add_return(1, &iscsi_session_nr);
20677970634bSMike Christie
20685842ea36SMike Christie session->workq = alloc_workqueue("iscsi_ctrl_%d:%d",
20695842ea36SMike Christie WQ_SYSFS | WQ_MEM_RECLAIM | WQ_UNBOUND, 0,
20705842ea36SMike Christie shost->host_no, session->sid);
20715842ea36SMike Christie if (!session->workq)
20725842ea36SMike Christie return -ENOMEM;
20735842ea36SMike Christie
20748d4a690cSMike Christie if (target_id == ISCSI_MAX_TARGET) {
20753fd3a52cSkeliu id = ida_alloc(&iscsi_sess_ida, GFP_KERNEL);
20767970634bSMike Christie
20778d4a690cSMike Christie if (id < 0) {
20787970634bSMike Christie iscsi_cls_session_printk(KERN_ERR, session,
20798d4a690cSMike Christie "Failure in Target ID Allocation\n");
20805842ea36SMike Christie err = id;
20815842ea36SMike Christie goto destroy_wq;
20827970634bSMike Christie }
20838d4a690cSMike Christie session->target_id = (unsigned int)id;
20848d4a690cSMike Christie session->ida_used = true;
20858d4a690cSMike Christie } else
20868d4a690cSMike Christie session->target_id = target_id;
2087a3be19b9SWenchao Hao spin_lock_irqsave(&session->lock, flags);
2088a3be19b9SWenchao Hao session->target_state = ISCSI_SESSION_TARGET_ALLOCATED;
2089a3be19b9SWenchao Hao spin_unlock_irqrestore(&session->lock, flags);
209030a6c652SMike Christie
209171610f55SKay Sievers dev_set_name(&session->dev, "session%u", session->sid);
20928434aa8bSMike Christie err = device_add(&session->dev);
20937b8631b5SMike Christie if (err) {
2094322d739dSMike Christie iscsi_cls_session_printk(KERN_ERR, session,
2095322d739dSMike Christie "could not register session's dev\n");
20968d4a690cSMike Christie goto release_ida;
20977b8631b5SMike Christie }
2098f3c893e3SGabriel Krisman Bertazi err = transport_register_device(&session->dev);
2099f3c893e3SGabriel Krisman Bertazi if (err) {
2100f3c893e3SGabriel Krisman Bertazi iscsi_cls_session_printk(KERN_ERR, session,
2101f3c893e3SGabriel Krisman Bertazi "could not register transport's dev\n");
2102f3c893e3SGabriel Krisman Bertazi goto release_dev;
2103f3c893e3SGabriel Krisman Bertazi }
21047b8631b5SMike Christie
210526974789SMike Christie spin_lock_irqsave(&sesslock, flags);
210626974789SMike Christie list_add(&session->sess_list, &sesslist);
210726974789SMike Christie spin_unlock_irqrestore(&sesslock, flags);
210826974789SMike Christie
210926974789SMike Christie iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);
2110632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completed session adding\n");
21118434aa8bSMike Christie return 0;
211230a6c652SMike Christie
2113f3c893e3SGabriel Krisman Bertazi release_dev:
2114f3c893e3SGabriel Krisman Bertazi device_del(&session->dev);
21158d4a690cSMike Christie release_ida:
21168d4a690cSMike Christie if (session->ida_used)
21173fd3a52cSkeliu ida_free(&iscsi_sess_ida, session->target_id);
21185842ea36SMike Christie destroy_wq:
21195842ea36SMike Christie destroy_workqueue(session->workq);
21208434aa8bSMike Christie return err;
21217b8631b5SMike Christie }
21228434aa8bSMike Christie EXPORT_SYMBOL_GPL(iscsi_add_session);
21237b8631b5SMike Christie
21247b8631b5SMike Christie /**
21258434aa8bSMike Christie * iscsi_create_session - create iscsi class session
21268434aa8bSMike Christie * @shost: scsi host
21278434aa8bSMike Christie * @transport: iscsi transport
21285d91e209SMike Christie * @dd_size: private driver data size
2129eb44820cSRob Landley * @target_id: which target
21307b8631b5SMike Christie *
21318434aa8bSMike Christie * This can be called from a LLD or iscsi_transport.
2132eb44820cSRob Landley */
21338434aa8bSMike Christie struct iscsi_cls_session *
iscsi_create_session(struct Scsi_Host * shost,struct iscsi_transport * transport,int dd_size,unsigned int target_id)21345d91e209SMike Christie iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
21355d91e209SMike Christie int dd_size, unsigned int target_id)
21368434aa8bSMike Christie {
21378434aa8bSMike Christie struct iscsi_cls_session *session;
21388434aa8bSMike Christie
21395d91e209SMike Christie session = iscsi_alloc_session(shost, transport, dd_size);
21408434aa8bSMike Christie if (!session)
21418434aa8bSMike Christie return NULL;
21428434aa8bSMike Christie
21436a8a0d36SMike Christie if (iscsi_add_session(session, target_id)) {
21448434aa8bSMike Christie iscsi_free_session(session);
21458434aa8bSMike Christie return NULL;
21468434aa8bSMike Christie }
21478434aa8bSMike Christie return session;
21488434aa8bSMike Christie }
21498434aa8bSMike Christie EXPORT_SYMBOL_GPL(iscsi_create_session);
21508434aa8bSMike Christie
iscsi_conn_release(struct device * dev)215126974789SMike Christie static void iscsi_conn_release(struct device *dev)
215226974789SMike Christie {
215326974789SMike Christie struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev);
215426974789SMike Christie struct device *parent = conn->dev.parent;
215526974789SMike Christie
2156632248aaSMike Christie ISCSI_DBG_TRANS_CONN(conn, "Releasing conn\n");
215726974789SMike Christie kfree(conn);
215826974789SMike Christie put_device(parent);
215926974789SMike Christie }
216026974789SMike Christie
iscsi_is_conn_dev(const struct device * dev)216126974789SMike Christie static int iscsi_is_conn_dev(const struct device *dev)
216226974789SMike Christie {
216326974789SMike Christie return dev->release == iscsi_conn_release;
216426974789SMike Christie }
216526974789SMike Christie
iscsi_iter_destroy_conn_fn(struct device * dev,void * data)216626974789SMike Christie static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
216726974789SMike Christie {
216826974789SMike Christie if (!iscsi_is_conn_dev(dev))
216926974789SMike Christie return 0;
21708709c323SWenchao Hao
21718709c323SWenchao Hao iscsi_remove_conn(iscsi_dev_to_conn(dev));
21728709c323SWenchao Hao return 0;
217326974789SMike Christie }
217426974789SMike Christie
iscsi_remove_session(struct iscsi_cls_session * session)21758434aa8bSMike Christie void iscsi_remove_session(struct iscsi_cls_session *session)
21767b8631b5SMike Christie {
217726974789SMike Christie unsigned long flags;
217826974789SMike Christie int err;
217930a6c652SMike Christie
2180632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Removing session\n");
2181632248aaSMike Christie
218226974789SMike Christie spin_lock_irqsave(&sesslock, flags);
218393bf02e5SMike Christie if (!list_empty(&session->sess_list))
218426974789SMike Christie list_del(&session->sess_list);
218526974789SMike Christie spin_unlock_irqrestore(&sesslock, flags);
218626974789SMike Christie
2187b07c348fSMike Christie if (!cancel_work_sync(&session->block_work))
21881d726aa6SMike Christie cancel_delayed_work_sync(&session->recovery_work);
2189b07c348fSMike Christie cancel_work_sync(&session->unblock_work);
219026974789SMike Christie /*
219126974789SMike Christie * If we are blocked let commands flow again. The lld or iscsi
219226974789SMike Christie * layer should set up the queuecommand to fail commands.
219345ab33b6SMike Christie * We assume that LLD will not be calling block/unblock while
219445ab33b6SMike Christie * removing the session.
219526974789SMike Christie */
21966eabafbeSMike Christie spin_lock_irqsave(&session->lock, flags);
21976eabafbeSMike Christie session->state = ISCSI_SESSION_FREE;
21986eabafbeSMike Christie spin_unlock_irqrestore(&session->lock, flags);
2199bd976f62SMike Christie
22005d9fb5ccSMike Christie scsi_target_unblock(&session->dev, SDEV_TRANSPORT_OFFLINE);
2201d8ec5d67SMike Christie /*
2202d8ec5d67SMike Christie * qla4xxx can perform it's own scans when it runs in kernel only
2203d8ec5d67SMike Christie * mode. Make sure to flush those scans.
2204d8ec5d67SMike Christie */
220590e96313SJitendra Bhivare flush_work(&session->scan_work);
2206165aa2bfSMaurizio Lombardi /* flush running unbind operations */
2207165aa2bfSMaurizio Lombardi flush_work(&session->unbind_work);
220845ab33b6SMike Christie __iscsi_unbind_session(&session->unbind_work);
220930a6c652SMike Christie
221026974789SMike Christie /* hw iscsi may not have removed all connections from session */
221126974789SMike Christie err = device_for_each_child(&session->dev, NULL,
221226974789SMike Christie iscsi_iter_destroy_conn_fn);
221326974789SMike Christie if (err)
2214322d739dSMike Christie iscsi_cls_session_printk(KERN_ERR, session,
2215322d739dSMike Christie "Could not delete all connections "
2216322d739dSMike Christie "for session. Error %d.\n", err);
22178434aa8bSMike Christie
22187b8631b5SMike Christie transport_unregister_device(&session->dev);
2219632248aaSMike Christie
22205842ea36SMike Christie destroy_workqueue(session->workq);
22215842ea36SMike Christie
2222632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completing session removal\n");
22238434aa8bSMike Christie device_del(&session->dev);
22248434aa8bSMike Christie }
22258434aa8bSMike Christie EXPORT_SYMBOL_GPL(iscsi_remove_session);
22268434aa8bSMike Christie
iscsi_stop_conn(struct iscsi_cls_conn * conn,int flag)222723d6fefbSMike Christie static void iscsi_stop_conn(struct iscsi_cls_conn *conn, int flag)
222823d6fefbSMike Christie {
222923d6fefbSMike Christie ISCSI_DBG_TRANS_CONN(conn, "Stopping conn.\n");
223023d6fefbSMike Christie
223123d6fefbSMike Christie switch (flag) {
223223d6fefbSMike Christie case STOP_CONN_RECOVER:
223303690d81SMike Christie WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
223423d6fefbSMike Christie break;
223523d6fefbSMike Christie case STOP_CONN_TERM:
223603690d81SMike Christie WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
223723d6fefbSMike Christie break;
223823d6fefbSMike Christie default:
223923d6fefbSMike Christie iscsi_cls_conn_printk(KERN_ERR, conn, "invalid stop flag %d\n",
224023d6fefbSMike Christie flag);
224123d6fefbSMike Christie return;
224223d6fefbSMike Christie }
224323d6fefbSMike Christie
224423d6fefbSMike Christie conn->transport->stop_conn(conn, flag);
224523d6fefbSMike Christie ISCSI_DBG_TRANS_CONN(conn, "Stopping conn done.\n");
224623d6fefbSMike Christie }
224723d6fefbSMike Christie
iscsi_ep_disconnect(struct iscsi_cls_conn * conn,bool is_active)2248c34f95e9SMike Christie static void iscsi_ep_disconnect(struct iscsi_cls_conn *conn, bool is_active)
2249c34f95e9SMike Christie {
2250c34f95e9SMike Christie struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
2251c34f95e9SMike Christie struct iscsi_endpoint *ep;
2252c34f95e9SMike Christie
2253c34f95e9SMike Christie ISCSI_DBG_TRANS_CONN(conn, "disconnect ep.\n");
225403690d81SMike Christie WRITE_ONCE(conn->state, ISCSI_CONN_FAILED);
2255c34f95e9SMike Christie
2256c34f95e9SMike Christie if (!conn->ep || !session->transport->ep_disconnect)
2257c34f95e9SMike Christie return;
2258c34f95e9SMike Christie
2259c34f95e9SMike Christie ep = conn->ep;
2260c34f95e9SMike Christie conn->ep = NULL;
2261c34f95e9SMike Christie
2262c34f95e9SMike Christie session->transport->unbind_conn(conn, is_active);
2263c34f95e9SMike Christie session->transport->ep_disconnect(ep);
2264c34f95e9SMike Christie ISCSI_DBG_TRANS_CONN(conn, "disconnect ep done.\n");
2265c34f95e9SMike Christie }
2266c34f95e9SMike Christie
iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn * conn,struct iscsi_endpoint * ep,bool is_active)2267cbd2283aSMike Christie static void iscsi_if_disconnect_bound_ep(struct iscsi_cls_conn *conn,
2268cbd2283aSMike Christie struct iscsi_endpoint *ep,
2269cbd2283aSMike Christie bool is_active)
2270cbd2283aSMike Christie {
2271cbd2283aSMike Christie /* Check if this was a conn error and the kernel took ownership */
22727c6e99c1SMike Christie spin_lock_irq(&conn->lock);
2273cbd2283aSMike Christie if (!test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
22747c6e99c1SMike Christie spin_unlock_irq(&conn->lock);
2275cbd2283aSMike Christie iscsi_ep_disconnect(conn, is_active);
2276cbd2283aSMike Christie } else {
22777c6e99c1SMike Christie spin_unlock_irq(&conn->lock);
2278cbd2283aSMike Christie ISCSI_DBG_TRANS_CONN(conn, "flush kernel conn cleanup.\n");
2279cbd2283aSMike Christie mutex_unlock(&conn->ep_mutex);
2280cbd2283aSMike Christie
2281cbd2283aSMike Christie flush_work(&conn->cleanup_work);
22820aadafb5SMike Christie /*
22830aadafb5SMike Christie * Userspace is now done with the EP so we can release the ref
22840aadafb5SMike Christie * iscsi_cleanup_conn_work_fn took.
22850aadafb5SMike Christie */
22860aadafb5SMike Christie iscsi_put_endpoint(ep);
2287cbd2283aSMike Christie mutex_lock(&conn->ep_mutex);
2288cbd2283aSMike Christie }
2289cbd2283aSMike Christie }
2290cbd2283aSMike Christie
iscsi_if_stop_conn(struct iscsi_cls_conn * conn,int flag)22913328333bSMike Christie static int iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag)
229223d6fefbSMike Christie {
229323d6fefbSMike Christie ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop.\n");
229423d6fefbSMike Christie /*
2295da2f132dSMike Christie * For offload, iscsid may not know about the ep like when iscsid is
2296da2f132dSMike Christie * restarted or for kernel based session shutdown iscsid is not even
2297da2f132dSMike Christie * up. For these cases, we do the disconnect now.
2298da2f132dSMike Christie */
2299da2f132dSMike Christie mutex_lock(&conn->ep_mutex);
2300da2f132dSMike Christie if (conn->ep)
2301da2f132dSMike Christie iscsi_if_disconnect_bound_ep(conn, conn->ep, true);
2302da2f132dSMike Christie mutex_unlock(&conn->ep_mutex);
2303da2f132dSMike Christie
2304da2f132dSMike Christie /*
230523d6fefbSMike Christie * If this is a termination we have to call stop_conn with that flag
230623d6fefbSMike Christie * so the correct states get set. If we haven't run the work yet try to
230723d6fefbSMike Christie * avoid the extra run.
230823d6fefbSMike Christie */
230923d6fefbSMike Christie if (flag == STOP_CONN_TERM) {
231023d6fefbSMike Christie cancel_work_sync(&conn->cleanup_work);
231123d6fefbSMike Christie iscsi_stop_conn(conn, flag);
231223d6fefbSMike Christie } else {
231323d6fefbSMike Christie /*
231423d6fefbSMike Christie * Figure out if it was the kernel or userspace initiating this.
231523d6fefbSMike Christie */
23167c6e99c1SMike Christie spin_lock_irq(&conn->lock);
231723d6fefbSMike Christie if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
23187c6e99c1SMike Christie spin_unlock_irq(&conn->lock);
231923d6fefbSMike Christie iscsi_stop_conn(conn, flag);
232023d6fefbSMike Christie } else {
23217c6e99c1SMike Christie spin_unlock_irq(&conn->lock);
232223d6fefbSMike Christie ISCSI_DBG_TRANS_CONN(conn,
232323d6fefbSMike Christie "flush kernel conn cleanup.\n");
232423d6fefbSMike Christie flush_work(&conn->cleanup_work);
232523d6fefbSMike Christie }
232623d6fefbSMike Christie /*
232723d6fefbSMike Christie * Only clear for recovery to avoid extra cleanup runs during
232823d6fefbSMike Christie * termination.
232923d6fefbSMike Christie */
23307c6e99c1SMike Christie spin_lock_irq(&conn->lock);
233123d6fefbSMike Christie clear_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags);
23327c6e99c1SMike Christie spin_unlock_irq(&conn->lock);
233323d6fefbSMike Christie }
233423d6fefbSMike Christie ISCSI_DBG_TRANS_CONN(conn, "iscsi if conn stop done.\n");
233523d6fefbSMike Christie return 0;
233623d6fefbSMike Christie }
233723d6fefbSMike Christie
iscsi_cleanup_conn_work_fn(struct work_struct * work)233823d6fefbSMike Christie static void iscsi_cleanup_conn_work_fn(struct work_struct *work)
233923d6fefbSMike Christie {
234023d6fefbSMike Christie struct iscsi_cls_conn *conn = container_of(work, struct iscsi_cls_conn,
234123d6fefbSMike Christie cleanup_work);
234223d6fefbSMike Christie struct iscsi_cls_session *session = iscsi_conn_to_session(conn);
234323d6fefbSMike Christie
234423d6fefbSMike Christie mutex_lock(&conn->ep_mutex);
234523d6fefbSMike Christie /*
23460aadafb5SMike Christie * Get a ref to the ep, so we don't release its ID until after
23470aadafb5SMike Christie * userspace is done referencing it in iscsi_if_disconnect_bound_ep.
23480aadafb5SMike Christie */
23490aadafb5SMike Christie if (conn->ep)
23500aadafb5SMike Christie get_device(&conn->ep->dev);
235123d6fefbSMike Christie iscsi_ep_disconnect(conn, false);
235223d6fefbSMike Christie
235323d6fefbSMike Christie if (system_state != SYSTEM_RUNNING) {
235423d6fefbSMike Christie /*
235523d6fefbSMike Christie * If the user has set up for the session to never timeout
235623d6fefbSMike Christie * then hang like they wanted. For all other cases fail right
235723d6fefbSMike Christie * away since userspace is not going to relogin.
235823d6fefbSMike Christie */
235923d6fefbSMike Christie if (session->recovery_tmo > 0)
236023d6fefbSMike Christie session->recovery_tmo = 0;
236123d6fefbSMike Christie }
236223d6fefbSMike Christie
236323d6fefbSMike Christie iscsi_stop_conn(conn, STOP_CONN_RECOVER);
236423d6fefbSMike Christie mutex_unlock(&conn->ep_mutex);
236523d6fefbSMike Christie ISCSI_DBG_TRANS_CONN(conn, "cleanup done.\n");
236623d6fefbSMike Christie }
236723d6fefbSMike Christie
iscsi_iter_force_destroy_conn_fn(struct device * dev,void * data)2368bb42856bSMike Christie static int iscsi_iter_force_destroy_conn_fn(struct device *dev, void *data)
2369bb42856bSMike Christie {
2370bb42856bSMike Christie struct iscsi_transport *transport;
2371bb42856bSMike Christie struct iscsi_cls_conn *conn;
2372bb42856bSMike Christie
2373bb42856bSMike Christie if (!iscsi_is_conn_dev(dev))
2374bb42856bSMike Christie return 0;
2375bb42856bSMike Christie
2376bb42856bSMike Christie conn = iscsi_dev_to_conn(dev);
2377bb42856bSMike Christie transport = conn->transport;
2378bb42856bSMike Christie
2379bb42856bSMike Christie if (READ_ONCE(conn->state) != ISCSI_CONN_DOWN)
2380bb42856bSMike Christie iscsi_if_stop_conn(conn, STOP_CONN_TERM);
2381bb42856bSMike Christie
2382bb42856bSMike Christie transport->destroy_conn(conn);
2383bb42856bSMike Christie return 0;
2384bb42856bSMike Christie }
2385bb42856bSMike Christie
2386bb42856bSMike Christie /**
2387bb42856bSMike Christie * iscsi_force_destroy_session - destroy a session from the kernel
2388bb42856bSMike Christie * @session: session to destroy
2389bb42856bSMike Christie *
2390bb42856bSMike Christie * Force the destruction of a session from the kernel. This should only be
2391bb42856bSMike Christie * used when userspace is no longer running during system shutdown.
2392bb42856bSMike Christie */
iscsi_force_destroy_session(struct iscsi_cls_session * session)2393bb42856bSMike Christie void iscsi_force_destroy_session(struct iscsi_cls_session *session)
2394bb42856bSMike Christie {
2395bb42856bSMike Christie struct iscsi_transport *transport = session->transport;
2396bb42856bSMike Christie unsigned long flags;
2397bb42856bSMike Christie
2398bb42856bSMike Christie WARN_ON_ONCE(system_state == SYSTEM_RUNNING);
2399bb42856bSMike Christie
2400bb42856bSMike Christie spin_lock_irqsave(&sesslock, flags);
2401bb42856bSMike Christie if (list_empty(&session->sess_list)) {
2402bb42856bSMike Christie spin_unlock_irqrestore(&sesslock, flags);
2403bb42856bSMike Christie /*
2404bb42856bSMike Christie * Conn/ep is already freed. Session is being torn down via
2405bb42856bSMike Christie * async path. For shutdown we don't care about it so return.
2406bb42856bSMike Christie */
2407bb42856bSMike Christie return;
2408bb42856bSMike Christie }
2409bb42856bSMike Christie spin_unlock_irqrestore(&sesslock, flags);
2410bb42856bSMike Christie
2411bb42856bSMike Christie device_for_each_child(&session->dev, NULL,
2412bb42856bSMike Christie iscsi_iter_force_destroy_conn_fn);
2413bb42856bSMike Christie transport->destroy_session(session);
2414bb42856bSMike Christie }
2415bb42856bSMike Christie EXPORT_SYMBOL_GPL(iscsi_force_destroy_session);
2416bb42856bSMike Christie
iscsi_free_session(struct iscsi_cls_session * session)24178434aa8bSMike Christie void iscsi_free_session(struct iscsi_cls_session *session)
24188434aa8bSMike Christie {
2419632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Freeing session\n");
242026974789SMike Christie iscsi_session_event(session, ISCSI_KEVENT_DESTROY_SESSION);
24218434aa8bSMike Christie put_device(&session->dev);
24227b8631b5SMike Christie }
24238434aa8bSMike Christie EXPORT_SYMBOL_GPL(iscsi_free_session);
24248434aa8bSMike Christie
24258434aa8bSMike Christie /**
2426ad515cadSWenchao Hao * iscsi_alloc_conn - alloc iscsi class connection
2427ad515cadSWenchao Hao * @session: iscsi cls session
2428ad515cadSWenchao Hao * @dd_size: private driver data size
2429ad515cadSWenchao Hao * @cid: connection id
2430ad515cadSWenchao Hao */
2431ad515cadSWenchao Hao struct iscsi_cls_conn *
iscsi_alloc_conn(struct iscsi_cls_session * session,int dd_size,uint32_t cid)2432ad515cadSWenchao Hao iscsi_alloc_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)
2433ad515cadSWenchao Hao {
2434ad515cadSWenchao Hao struct iscsi_transport *transport = session->transport;
2435ad515cadSWenchao Hao struct iscsi_cls_conn *conn;
2436ad515cadSWenchao Hao
2437ad515cadSWenchao Hao conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL);
2438ad515cadSWenchao Hao if (!conn)
2439ad515cadSWenchao Hao return NULL;
2440ad515cadSWenchao Hao if (dd_size)
2441ad515cadSWenchao Hao conn->dd_data = &conn[1];
2442ad515cadSWenchao Hao
2443ad515cadSWenchao Hao mutex_init(&conn->ep_mutex);
24447c6e99c1SMike Christie spin_lock_init(&conn->lock);
2445ad515cadSWenchao Hao INIT_LIST_HEAD(&conn->conn_list);
2446ad515cadSWenchao Hao INIT_WORK(&conn->cleanup_work, iscsi_cleanup_conn_work_fn);
2447ad515cadSWenchao Hao conn->transport = transport;
2448ad515cadSWenchao Hao conn->cid = cid;
244903690d81SMike Christie WRITE_ONCE(conn->state, ISCSI_CONN_DOWN);
2450ad515cadSWenchao Hao
2451ad515cadSWenchao Hao /* this is released in the dev's release function */
2452ad515cadSWenchao Hao if (!get_device(&session->dev))
2453ad515cadSWenchao Hao goto free_conn;
2454ad515cadSWenchao Hao
2455ad515cadSWenchao Hao dev_set_name(&conn->dev, "connection%d:%u", session->sid, cid);
2456ad515cadSWenchao Hao device_initialize(&conn->dev);
2457ad515cadSWenchao Hao conn->dev.parent = &session->dev;
2458ad515cadSWenchao Hao conn->dev.release = iscsi_conn_release;
2459ad515cadSWenchao Hao
2460ad515cadSWenchao Hao return conn;
2461ad515cadSWenchao Hao
2462ad515cadSWenchao Hao free_conn:
2463ad515cadSWenchao Hao kfree(conn);
2464ad515cadSWenchao Hao return NULL;
2465ad515cadSWenchao Hao }
2466ad515cadSWenchao Hao EXPORT_SYMBOL_GPL(iscsi_alloc_conn);
2467ad515cadSWenchao Hao
2468ad515cadSWenchao Hao /**
2469ad515cadSWenchao Hao * iscsi_add_conn - add iscsi class connection
2470ad515cadSWenchao Hao * @conn: iscsi cls connection
2471ad515cadSWenchao Hao *
2472ad515cadSWenchao Hao * This will expose iscsi_cls_conn to sysfs so make sure the related
2473ad515cadSWenchao Hao * resources for sysfs attributes are initialized before calling this.
2474ad515cadSWenchao Hao */
iscsi_add_conn(struct iscsi_cls_conn * conn)2475ad515cadSWenchao Hao int iscsi_add_conn(struct iscsi_cls_conn *conn)
2476ad515cadSWenchao Hao {
2477ad515cadSWenchao Hao int err;
2478ad515cadSWenchao Hao unsigned long flags;
2479ad515cadSWenchao Hao struct iscsi_cls_session *session = iscsi_dev_to_session(conn->dev.parent);
2480ad515cadSWenchao Hao
2481ad515cadSWenchao Hao err = device_add(&conn->dev);
2482ad515cadSWenchao Hao if (err) {
2483ad515cadSWenchao Hao iscsi_cls_session_printk(KERN_ERR, session,
2484ad515cadSWenchao Hao "could not register connection's dev\n");
2485ad515cadSWenchao Hao return err;
2486ad515cadSWenchao Hao }
2487ad515cadSWenchao Hao err = transport_register_device(&conn->dev);
2488ad515cadSWenchao Hao if (err) {
2489ad515cadSWenchao Hao iscsi_cls_session_printk(KERN_ERR, session,
2490ad515cadSWenchao Hao "could not register transport's dev\n");
2491ad515cadSWenchao Hao device_del(&conn->dev);
2492ad515cadSWenchao Hao return err;
2493ad515cadSWenchao Hao }
2494ad515cadSWenchao Hao
2495ad515cadSWenchao Hao spin_lock_irqsave(&connlock, flags);
2496ad515cadSWenchao Hao list_add(&conn->conn_list, &connlist);
2497ad515cadSWenchao Hao spin_unlock_irqrestore(&connlock, flags);
2498ad515cadSWenchao Hao
2499ad515cadSWenchao Hao return 0;
2500ad515cadSWenchao Hao }
2501ad515cadSWenchao Hao EXPORT_SYMBOL_GPL(iscsi_add_conn);
2502ad515cadSWenchao Hao
2503ad515cadSWenchao Hao /**
2504ad515cadSWenchao Hao * iscsi_remove_conn - remove iscsi class connection from sysfs
2505ad515cadSWenchao Hao * @conn: iscsi cls connection
2506ad515cadSWenchao Hao *
2507ad515cadSWenchao Hao * Remove iscsi_cls_conn from sysfs, and wait for previous
2508ad515cadSWenchao Hao * read/write of iscsi_cls_conn's attributes in sysfs to finish.
2509ad515cadSWenchao Hao */
iscsi_remove_conn(struct iscsi_cls_conn * conn)2510ad515cadSWenchao Hao void iscsi_remove_conn(struct iscsi_cls_conn *conn)
2511ad515cadSWenchao Hao {
2512ad515cadSWenchao Hao unsigned long flags;
2513ad515cadSWenchao Hao
2514ad515cadSWenchao Hao spin_lock_irqsave(&connlock, flags);
2515ad515cadSWenchao Hao list_del(&conn->conn_list);
2516ad515cadSWenchao Hao spin_unlock_irqrestore(&connlock, flags);
2517ad515cadSWenchao Hao
2518ad515cadSWenchao Hao transport_unregister_device(&conn->dev);
2519ad515cadSWenchao Hao device_del(&conn->dev);
2520ad515cadSWenchao Hao }
2521ad515cadSWenchao Hao EXPORT_SYMBOL_GPL(iscsi_remove_conn);
2522ad515cadSWenchao Hao
iscsi_put_conn(struct iscsi_cls_conn * conn)2523b1d19e8cSMike Christie void iscsi_put_conn(struct iscsi_cls_conn *conn)
2524b1d19e8cSMike Christie {
2525b1d19e8cSMike Christie put_device(&conn->dev);
2526b1d19e8cSMike Christie }
2527b1d19e8cSMike Christie EXPORT_SYMBOL_GPL(iscsi_put_conn);
2528b1d19e8cSMike Christie
iscsi_get_conn(struct iscsi_cls_conn * conn)2529b1d19e8cSMike Christie void iscsi_get_conn(struct iscsi_cls_conn *conn)
2530b1d19e8cSMike Christie {
2531b1d19e8cSMike Christie get_device(&conn->dev);
2532b1d19e8cSMike Christie }
2533b1d19e8cSMike Christie EXPORT_SYMBOL_GPL(iscsi_get_conn);
2534b1d19e8cSMike Christie
25357b8631b5SMike Christie /*
25367b8631b5SMike Christie * iscsi interface functions
25377b8631b5SMike Christie */
25380896b752SAlex Aizman static struct iscsi_internal *
iscsi_if_transport_lookup(struct iscsi_transport * tt)25390896b752SAlex Aizman iscsi_if_transport_lookup(struct iscsi_transport *tt)
25400896b752SAlex Aizman {
25410896b752SAlex Aizman struct iscsi_internal *priv;
25420896b752SAlex Aizman unsigned long flags;
25431da177e4SLinus Torvalds
25440896b752SAlex Aizman spin_lock_irqsave(&iscsi_transport_lock, flags);
25450896b752SAlex Aizman list_for_each_entry(priv, &iscsi_transports, list) {
25460896b752SAlex Aizman if (tt == priv->iscsi_transport) {
25470896b752SAlex Aizman spin_unlock_irqrestore(&iscsi_transport_lock, flags);
25480896b752SAlex Aizman return priv;
25490896b752SAlex Aizman }
25500896b752SAlex Aizman }
25510896b752SAlex Aizman spin_unlock_irqrestore(&iscsi_transport_lock, flags);
25520896b752SAlex Aizman return NULL;
25530896b752SAlex Aizman }
25541da177e4SLinus Torvalds
25550896b752SAlex Aizman static int
iscsi_multicast_skb(struct sk_buff * skb,uint32_t group,gfp_t gfp)255643514774SMichael Chan iscsi_multicast_skb(struct sk_buff *skb, uint32_t group, gfp_t gfp)
255753cb8a1fSMike Christie {
255843514774SMichael Chan return nlmsg_multicast(nls, skb, 0, group, gfp);
25590896b752SAlex Aizman }
25600896b752SAlex Aizman
2561af170928SChris Leech static int
iscsi_unicast_skb(struct sk_buff * skb,u32 portid)2562af170928SChris Leech iscsi_unicast_skb(struct sk_buff *skb, u32 portid)
2563af170928SChris Leech {
2564af170928SChris Leech return nlmsg_unicast(nls, skb, portid);
2565af170928SChris Leech }
2566af170928SChris Leech
iscsi_recv_pdu(struct iscsi_cls_conn * conn,struct iscsi_hdr * hdr,char * data,uint32_t data_size)25677b7232f3SMike Christie int iscsi_recv_pdu(struct iscsi_cls_conn *conn, struct iscsi_hdr *hdr,
25680896b752SAlex Aizman char *data, uint32_t data_size)
25690896b752SAlex Aizman {
25700896b752SAlex Aizman struct nlmsghdr *nlh;
25710896b752SAlex Aizman struct sk_buff *skb;
25720896b752SAlex Aizman struct iscsi_uevent *ev;
25730896b752SAlex Aizman char *pdu;
2574790f39a2SMike Christie struct iscsi_internal *priv;
2575e07ebea0SHong zhi guo int len = nlmsg_total_size(sizeof(*ev) + sizeof(struct iscsi_hdr) +
25760896b752SAlex Aizman data_size);
25770896b752SAlex Aizman
2578790f39a2SMike Christie priv = iscsi_if_transport_lookup(conn->transport);
2579790f39a2SMike Christie if (!priv)
2580790f39a2SMike Christie return -EINVAL;
2581790f39a2SMike Christie
258243a145a3SMike Christie skb = alloc_skb(len, GFP_ATOMIC);
25830896b752SAlex Aizman if (!skb) {
2584e5bd7b54SMike Christie iscsi_conn_error_event(conn, ISCSI_ERR_CONN_FAILED);
2585322d739dSMike Christie iscsi_cls_conn_printk(KERN_ERR, conn, "can not deliver "
25867b8631b5SMike Christie "control PDU: OOM\n");
25870896b752SAlex Aizman return -ENOMEM;
25880896b752SAlex Aizman }
25890896b752SAlex Aizman
259043514774SMichael Chan nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2591e07ebea0SHong zhi guo ev = nlmsg_data(nlh);
25920896b752SAlex Aizman memset(ev, 0, sizeof(*ev));
25930896b752SAlex Aizman ev->transport_handle = iscsi_handle(conn->transport);
25940896b752SAlex Aizman ev->type = ISCSI_KEVENT_RECV_PDU;
2595b5c7a12dSMike Christie ev->r.recv_req.cid = conn->cid;
2596b5c7a12dSMike Christie ev->r.recv_req.sid = iscsi_conn_get_sid(conn);
25970896b752SAlex Aizman pdu = (char*)ev + sizeof(*ev);
25980896b752SAlex Aizman memcpy(pdu, hdr, sizeof(struct iscsi_hdr));
25990896b752SAlex Aizman memcpy(pdu + sizeof(struct iscsi_hdr), data, data_size);
26000896b752SAlex Aizman
260143514774SMichael Chan return iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
26020896b752SAlex Aizman }
26030896b752SAlex Aizman EXPORT_SYMBOL_GPL(iscsi_recv_pdu);
26040896b752SAlex Aizman
iscsi_offload_mesg(struct Scsi_Host * shost,struct iscsi_transport * transport,uint32_t type,char * data,uint16_t data_size)260543514774SMichael Chan int iscsi_offload_mesg(struct Scsi_Host *shost,
260643514774SMichael Chan struct iscsi_transport *transport, uint32_t type,
260743514774SMichael Chan char *data, uint16_t data_size)
260843514774SMichael Chan {
260943514774SMichael Chan struct nlmsghdr *nlh;
261043514774SMichael Chan struct sk_buff *skb;
261143514774SMichael Chan struct iscsi_uevent *ev;
2612e07ebea0SHong zhi guo int len = nlmsg_total_size(sizeof(*ev) + data_size);
261343514774SMichael Chan
2614a541f840SMichael Chan skb = alloc_skb(len, GFP_ATOMIC);
261543514774SMichael Chan if (!skb) {
261643514774SMichael Chan printk(KERN_ERR "can not deliver iscsi offload message:OOM\n");
261743514774SMichael Chan return -ENOMEM;
261843514774SMichael Chan }
261943514774SMichael Chan
262043514774SMichael Chan nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2621e07ebea0SHong zhi guo ev = nlmsg_data(nlh);
262243514774SMichael Chan memset(ev, 0, sizeof(*ev));
262343514774SMichael Chan ev->type = type;
262443514774SMichael Chan ev->transport_handle = iscsi_handle(transport);
262543514774SMichael Chan switch (type) {
262643514774SMichael Chan case ISCSI_KEVENT_PATH_REQ:
262743514774SMichael Chan ev->r.req_path.host_no = shost->host_no;
262843514774SMichael Chan break;
262943514774SMichael Chan case ISCSI_KEVENT_IF_DOWN:
263043514774SMichael Chan ev->r.notify_if_down.host_no = shost->host_no;
263143514774SMichael Chan break;
263243514774SMichael Chan }
263343514774SMichael Chan
263443514774SMichael Chan memcpy((char *)ev + sizeof(*ev), data, data_size);
263543514774SMichael Chan
2636a541f840SMichael Chan return iscsi_multicast_skb(skb, ISCSI_NL_GRP_UIP, GFP_ATOMIC);
263743514774SMichael Chan }
263843514774SMichael Chan EXPORT_SYMBOL_GPL(iscsi_offload_mesg);
263943514774SMichael Chan
iscsi_conn_error_event(struct iscsi_cls_conn * conn,enum iscsi_err error)2640e5bd7b54SMike Christie void iscsi_conn_error_event(struct iscsi_cls_conn *conn, enum iscsi_err error)
26410896b752SAlex Aizman {
26420896b752SAlex Aizman struct nlmsghdr *nlh;
26430896b752SAlex Aizman struct sk_buff *skb;
26440896b752SAlex Aizman struct iscsi_uevent *ev;
2645790f39a2SMike Christie struct iscsi_internal *priv;
2646e07ebea0SHong zhi guo int len = nlmsg_total_size(sizeof(*ev));
26477c6e99c1SMike Christie unsigned long flags;
264803690d81SMike Christie int state;
26490ab71045SBharath Ravi
26507c6e99c1SMike Christie spin_lock_irqsave(&conn->lock, flags);
265103690d81SMike Christie /*
265203690d81SMike Christie * Userspace will only do a stop call if we are at least bound. And, we
265303690d81SMike Christie * only need to do the in kernel cleanup if in the UP state so cmds can
265403690d81SMike Christie * be released to upper layers. If in other states just wait for
265503690d81SMike Christie * userspace to avoid races that can leave the cleanup_work queued.
265603690d81SMike Christie */
265703690d81SMike Christie state = READ_ONCE(conn->state);
265803690d81SMike Christie switch (state) {
265903690d81SMike Christie case ISCSI_CONN_BOUND:
266003690d81SMike Christie case ISCSI_CONN_UP:
266103690d81SMike Christie if (!test_and_set_bit(ISCSI_CLS_CONN_BIT_CLEANUP,
266203690d81SMike Christie &conn->flags)) {
266303690d81SMike Christie queue_work(iscsi_conn_cleanup_workq,
266403690d81SMike Christie &conn->cleanup_work);
266503690d81SMike Christie }
266603690d81SMike Christie break;
266703690d81SMike Christie default:
266803690d81SMike Christie ISCSI_DBG_TRANS_CONN(conn, "Got conn error in state %d\n",
266903690d81SMike Christie state);
267003690d81SMike Christie break;
267103690d81SMike Christie }
26727c6e99c1SMike Christie spin_unlock_irqrestore(&conn->lock, flags);
26730896b752SAlex Aizman
2674790f39a2SMike Christie priv = iscsi_if_transport_lookup(conn->transport);
2675790f39a2SMike Christie if (!priv)
2676790f39a2SMike Christie return;
2677790f39a2SMike Christie
267843a145a3SMike Christie skb = alloc_skb(len, GFP_ATOMIC);
26790896b752SAlex Aizman if (!skb) {
2680322d739dSMike Christie iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
26817b8631b5SMike Christie "conn error (%d)\n", error);
26820896b752SAlex Aizman return;
26830896b752SAlex Aizman }
26840896b752SAlex Aizman
268543514774SMichael Chan nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2686e07ebea0SHong zhi guo ev = nlmsg_data(nlh);
26870896b752SAlex Aizman ev->transport_handle = iscsi_handle(conn->transport);
26880896b752SAlex Aizman ev->type = ISCSI_KEVENT_CONN_ERROR;
26890896b752SAlex Aizman ev->r.connerror.error = error;
2690b5c7a12dSMike Christie ev->r.connerror.cid = conn->cid;
2691b5c7a12dSMike Christie ev->r.connerror.sid = iscsi_conn_get_sid(conn);
26920896b752SAlex Aizman
269343514774SMichael Chan iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
26940896b752SAlex Aizman
2695322d739dSMike Christie iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn error (%d)\n",
26967b8631b5SMike Christie error);
26970896b752SAlex Aizman }
2698e5bd7b54SMike Christie EXPORT_SYMBOL_GPL(iscsi_conn_error_event);
26990896b752SAlex Aizman
iscsi_conn_login_event(struct iscsi_cls_conn * conn,enum iscsi_conn_state state)270017fa575eSManish Rangankar void iscsi_conn_login_event(struct iscsi_cls_conn *conn,
270117fa575eSManish Rangankar enum iscsi_conn_state state)
270217fa575eSManish Rangankar {
270317fa575eSManish Rangankar struct nlmsghdr *nlh;
270417fa575eSManish Rangankar struct sk_buff *skb;
270517fa575eSManish Rangankar struct iscsi_uevent *ev;
270617fa575eSManish Rangankar struct iscsi_internal *priv;
2707e07ebea0SHong zhi guo int len = nlmsg_total_size(sizeof(*ev));
270817fa575eSManish Rangankar
270917fa575eSManish Rangankar priv = iscsi_if_transport_lookup(conn->transport);
271017fa575eSManish Rangankar if (!priv)
271117fa575eSManish Rangankar return;
271217fa575eSManish Rangankar
271317fa575eSManish Rangankar skb = alloc_skb(len, GFP_ATOMIC);
271417fa575eSManish Rangankar if (!skb) {
271517fa575eSManish Rangankar iscsi_cls_conn_printk(KERN_ERR, conn, "gracefully ignored "
271617fa575eSManish Rangankar "conn login (%d)\n", state);
271717fa575eSManish Rangankar return;
271817fa575eSManish Rangankar }
271917fa575eSManish Rangankar
272017fa575eSManish Rangankar nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2721e07ebea0SHong zhi guo ev = nlmsg_data(nlh);
272217fa575eSManish Rangankar ev->transport_handle = iscsi_handle(conn->transport);
272317fa575eSManish Rangankar ev->type = ISCSI_KEVENT_CONN_LOGIN_STATE;
272417fa575eSManish Rangankar ev->r.conn_login.state = state;
272517fa575eSManish Rangankar ev->r.conn_login.cid = conn->cid;
272617fa575eSManish Rangankar ev->r.conn_login.sid = iscsi_conn_get_sid(conn);
272717fa575eSManish Rangankar iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_ATOMIC);
272817fa575eSManish Rangankar
272917fa575eSManish Rangankar iscsi_cls_conn_printk(KERN_INFO, conn, "detected conn login (%d)\n",
273017fa575eSManish Rangankar state);
273117fa575eSManish Rangankar }
273217fa575eSManish Rangankar EXPORT_SYMBOL_GPL(iscsi_conn_login_event);
273317fa575eSManish Rangankar
iscsi_post_host_event(uint32_t host_no,struct iscsi_transport * transport,enum iscsi_host_event_code code,uint32_t data_size,uint8_t * data)2734a11e2545SVikas Chaudhary void iscsi_post_host_event(uint32_t host_no, struct iscsi_transport *transport,
2735a11e2545SVikas Chaudhary enum iscsi_host_event_code code, uint32_t data_size,
2736a11e2545SVikas Chaudhary uint8_t *data)
2737a11e2545SVikas Chaudhary {
2738a11e2545SVikas Chaudhary struct nlmsghdr *nlh;
2739a11e2545SVikas Chaudhary struct sk_buff *skb;
2740a11e2545SVikas Chaudhary struct iscsi_uevent *ev;
2741e07ebea0SHong zhi guo int len = nlmsg_total_size(sizeof(*ev) + data_size);
2742a11e2545SVikas Chaudhary
274349d0e64bSMike Christie skb = alloc_skb(len, GFP_NOIO);
2744a11e2545SVikas Chaudhary if (!skb) {
2745a11e2545SVikas Chaudhary printk(KERN_ERR "gracefully ignored host event (%d):%d OOM\n",
2746a11e2545SVikas Chaudhary host_no, code);
2747a11e2545SVikas Chaudhary return;
2748a11e2545SVikas Chaudhary }
2749a11e2545SVikas Chaudhary
2750a11e2545SVikas Chaudhary nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2751e07ebea0SHong zhi guo ev = nlmsg_data(nlh);
2752a11e2545SVikas Chaudhary ev->transport_handle = iscsi_handle(transport);
2753a11e2545SVikas Chaudhary ev->type = ISCSI_KEVENT_HOST_EVENT;
2754a11e2545SVikas Chaudhary ev->r.host_event.host_no = host_no;
2755a11e2545SVikas Chaudhary ev->r.host_event.code = code;
2756a11e2545SVikas Chaudhary ev->r.host_event.data_size = data_size;
2757a11e2545SVikas Chaudhary
2758a11e2545SVikas Chaudhary if (data_size)
2759a11e2545SVikas Chaudhary memcpy((char *)ev + sizeof(*ev), data, data_size);
2760a11e2545SVikas Chaudhary
276149d0e64bSMike Christie iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
2762a11e2545SVikas Chaudhary }
2763a11e2545SVikas Chaudhary EXPORT_SYMBOL_GPL(iscsi_post_host_event);
2764a11e2545SVikas Chaudhary
iscsi_ping_comp_event(uint32_t host_no,struct iscsi_transport * transport,uint32_t status,uint32_t pid,uint32_t data_size,uint8_t * data)2765ac20c7bfSVikas Chaudhary void iscsi_ping_comp_event(uint32_t host_no, struct iscsi_transport *transport,
2766ac20c7bfSVikas Chaudhary uint32_t status, uint32_t pid, uint32_t data_size,
2767ac20c7bfSVikas Chaudhary uint8_t *data)
2768ac20c7bfSVikas Chaudhary {
2769ac20c7bfSVikas Chaudhary struct nlmsghdr *nlh;
2770ac20c7bfSVikas Chaudhary struct sk_buff *skb;
2771ac20c7bfSVikas Chaudhary struct iscsi_uevent *ev;
2772e07ebea0SHong zhi guo int len = nlmsg_total_size(sizeof(*ev) + data_size);
2773ac20c7bfSVikas Chaudhary
277449d0e64bSMike Christie skb = alloc_skb(len, GFP_NOIO);
2775ac20c7bfSVikas Chaudhary if (!skb) {
2776ac20c7bfSVikas Chaudhary printk(KERN_ERR "gracefully ignored ping comp: OOM\n");
2777ac20c7bfSVikas Chaudhary return;
2778ac20c7bfSVikas Chaudhary }
2779ac20c7bfSVikas Chaudhary
2780ac20c7bfSVikas Chaudhary nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2781e07ebea0SHong zhi guo ev = nlmsg_data(nlh);
2782ac20c7bfSVikas Chaudhary ev->transport_handle = iscsi_handle(transport);
2783ac20c7bfSVikas Chaudhary ev->type = ISCSI_KEVENT_PING_COMP;
2784ac20c7bfSVikas Chaudhary ev->r.ping_comp.host_no = host_no;
2785ac20c7bfSVikas Chaudhary ev->r.ping_comp.status = status;
2786ac20c7bfSVikas Chaudhary ev->r.ping_comp.pid = pid;
2787ac20c7bfSVikas Chaudhary ev->r.ping_comp.data_size = data_size;
2788ac20c7bfSVikas Chaudhary memcpy((char *)ev + sizeof(*ev), data, data_size);
2789ac20c7bfSVikas Chaudhary
279049d0e64bSMike Christie iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_NOIO);
2791ac20c7bfSVikas Chaudhary }
2792ac20c7bfSVikas Chaudhary EXPORT_SYMBOL_GPL(iscsi_ping_comp_event);
2793ac20c7bfSVikas Chaudhary
27940896b752SAlex Aizman static int
iscsi_if_send_reply(u32 portid,int type,void * payload,int size)2795af170928SChris Leech iscsi_if_send_reply(u32 portid, int type, void *payload, int size)
27960896b752SAlex Aizman {
27970896b752SAlex Aizman struct sk_buff *skb;
27980896b752SAlex Aizman struct nlmsghdr *nlh;
2799e07ebea0SHong zhi guo int len = nlmsg_total_size(size);
28000896b752SAlex Aizman
280143a145a3SMike Christie skb = alloc_skb(len, GFP_ATOMIC);
2802239a7dc2SMike Christie if (!skb) {
2803239a7dc2SMike Christie printk(KERN_ERR "Could not allocate skb to send reply.\n");
2804239a7dc2SMike Christie return -ENOMEM;
2805239a7dc2SMike Christie }
28060896b752SAlex Aizman
2807af170928SChris Leech nlh = __nlmsg_put(skb, 0, 0, type, (len - sizeof(*nlh)), 0);
2808e07ebea0SHong zhi guo memcpy(nlmsg_data(nlh), payload, size);
2809af170928SChris Leech return iscsi_unicast_skb(skb, portid);
28100896b752SAlex Aizman }
28110896b752SAlex Aizman
28120896b752SAlex Aizman static int
iscsi_if_get_stats(struct iscsi_transport * transport,struct nlmsghdr * nlh)28135b940adfSMike Christie iscsi_if_get_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
28140896b752SAlex Aizman {
2815e07ebea0SHong zhi guo struct iscsi_uevent *ev = nlmsg_data(nlh);
28160896b752SAlex Aizman struct iscsi_stats *stats;
28170896b752SAlex Aizman struct sk_buff *skbstat;
28187b8631b5SMike Christie struct iscsi_cls_conn *conn;
28190896b752SAlex Aizman struct nlmsghdr *nlhstat;
28200896b752SAlex Aizman struct iscsi_uevent *evstat;
2821790f39a2SMike Christie struct iscsi_internal *priv;
2822e07ebea0SHong zhi guo int len = nlmsg_total_size(sizeof(*ev) +
28230896b752SAlex Aizman sizeof(struct iscsi_stats) +
28240896b752SAlex Aizman sizeof(struct iscsi_stats_custom) *
28250896b752SAlex Aizman ISCSI_STATS_CUSTOM_MAX);
28260896b752SAlex Aizman int err = 0;
28270896b752SAlex Aizman
2828790f39a2SMike Christie priv = iscsi_if_transport_lookup(transport);
2829790f39a2SMike Christie if (!priv)
2830790f39a2SMike Christie return -EINVAL;
2831790f39a2SMike Christie
2832b5c7a12dSMike Christie conn = iscsi_conn_lookup(ev->u.get_stats.sid, ev->u.get_stats.cid);
28330896b752SAlex Aizman if (!conn)
28340896b752SAlex Aizman return -EEXIST;
28350896b752SAlex Aizman
28360896b752SAlex Aizman do {
28370896b752SAlex Aizman int actual_size;
28380896b752SAlex Aizman
283943a145a3SMike Christie skbstat = alloc_skb(len, GFP_ATOMIC);
28400896b752SAlex Aizman if (!skbstat) {
2841322d739dSMike Christie iscsi_cls_conn_printk(KERN_ERR, conn, "can not "
28427b8631b5SMike Christie "deliver stats: OOM\n");
28430896b752SAlex Aizman return -ENOMEM;
28440896b752SAlex Aizman }
28450896b752SAlex Aizman
284643514774SMichael Chan nlhstat = __nlmsg_put(skbstat, 0, 0, 0,
28470896b752SAlex Aizman (len - sizeof(*nlhstat)), 0);
2848e07ebea0SHong zhi guo evstat = nlmsg_data(nlhstat);
28490896b752SAlex Aizman memset(evstat, 0, sizeof(*evstat));
28500896b752SAlex Aizman evstat->transport_handle = iscsi_handle(conn->transport);
28510896b752SAlex Aizman evstat->type = nlh->nlmsg_type;
2852b5c7a12dSMike Christie evstat->u.get_stats.cid =
2853b5c7a12dSMike Christie ev->u.get_stats.cid;
2854b5c7a12dSMike Christie evstat->u.get_stats.sid =
2855b5c7a12dSMike Christie ev->u.get_stats.sid;
28560896b752SAlex Aizman stats = (struct iscsi_stats *)
28570896b752SAlex Aizman ((char*)evstat + sizeof(*evstat));
28580896b752SAlex Aizman memset(stats, 0, sizeof(*stats));
28590896b752SAlex Aizman
28607b7232f3SMike Christie transport->get_stats(conn, stats);
2861e07ebea0SHong zhi guo actual_size = nlmsg_total_size(sizeof(struct iscsi_uevent) +
28620896b752SAlex Aizman sizeof(struct iscsi_stats) +
28630896b752SAlex Aizman sizeof(struct iscsi_stats_custom) *
28640896b752SAlex Aizman stats->custom_length);
28650896b752SAlex Aizman actual_size -= sizeof(*nlhstat);
2866e07ebea0SHong zhi guo actual_size = nlmsg_msg_size(actual_size);
28675b940adfSMike Christie skb_trim(skbstat, NLMSG_ALIGN(actual_size));
28680896b752SAlex Aizman nlhstat->nlmsg_len = actual_size;
28690896b752SAlex Aizman
287043514774SMichael Chan err = iscsi_multicast_skb(skbstat, ISCSI_NL_GRP_ISCSID,
287143514774SMichael Chan GFP_ATOMIC);
28720896b752SAlex Aizman } while (err < 0 && err != -ECONNREFUSED);
28730896b752SAlex Aizman
28740896b752SAlex Aizman return err;
28750896b752SAlex Aizman }
28760896b752SAlex Aizman
287753cb8a1fSMike Christie /**
287826974789SMike Christie * iscsi_session_event - send session destr. completion event
287926974789SMike Christie * @session: iscsi class session
288026974789SMike Christie * @event: type of event
2881eb44820cSRob Landley */
iscsi_session_event(struct iscsi_cls_session * session,enum iscsi_uevent_e event)288226974789SMike Christie int iscsi_session_event(struct iscsi_cls_session *session,
288326974789SMike Christie enum iscsi_uevent_e event)
288453cb8a1fSMike Christie {
288553cb8a1fSMike Christie struct iscsi_internal *priv;
288653cb8a1fSMike Christie struct Scsi_Host *shost;
288753cb8a1fSMike Christie struct iscsi_uevent *ev;
288853cb8a1fSMike Christie struct sk_buff *skb;
288953cb8a1fSMike Christie struct nlmsghdr *nlh;
2890e07ebea0SHong zhi guo int rc, len = nlmsg_total_size(sizeof(*ev));
289153cb8a1fSMike Christie
289226974789SMike Christie priv = iscsi_if_transport_lookup(session->transport);
289353cb8a1fSMike Christie if (!priv)
289453cb8a1fSMike Christie return -EINVAL;
289553cb8a1fSMike Christie shost = iscsi_session_to_shost(session);
289653cb8a1fSMike Christie
289743a145a3SMike Christie skb = alloc_skb(len, GFP_KERNEL);
289853cb8a1fSMike Christie if (!skb) {
2899322d739dSMike Christie iscsi_cls_session_printk(KERN_ERR, session,
2900322d739dSMike Christie "Cannot notify userspace of session "
2901322d739dSMike Christie "event %u\n", event);
290253cb8a1fSMike Christie return -ENOMEM;
290353cb8a1fSMike Christie }
290453cb8a1fSMike Christie
290543514774SMichael Chan nlh = __nlmsg_put(skb, 0, 0, 0, (len - sizeof(*nlh)), 0);
2906e07ebea0SHong zhi guo ev = nlmsg_data(nlh);
290726974789SMike Christie ev->transport_handle = iscsi_handle(session->transport);
290826974789SMike Christie
290926974789SMike Christie ev->type = event;
291026974789SMike Christie switch (event) {
291126974789SMike Christie case ISCSI_KEVENT_DESTROY_SESSION:
291253cb8a1fSMike Christie ev->r.d_session.host_no = shost->host_no;
291353cb8a1fSMike Christie ev->r.d_session.sid = session->sid;
291426974789SMike Christie break;
291526974789SMike Christie case ISCSI_KEVENT_CREATE_SESSION:
291653cb8a1fSMike Christie ev->r.c_session_ret.host_no = shost->host_no;
291753cb8a1fSMike Christie ev->r.c_session_ret.sid = session->sid;
291826974789SMike Christie break;
291926974789SMike Christie case ISCSI_KEVENT_UNBIND_SESSION:
292026974789SMike Christie ev->r.unbind_session.host_no = shost->host_no;
292126974789SMike Christie ev->r.unbind_session.sid = session->sid;
292226974789SMike Christie break;
292326974789SMike Christie default:
2924322d739dSMike Christie iscsi_cls_session_printk(KERN_ERR, session, "Invalid event "
2925322d739dSMike Christie "%u.\n", event);
292626974789SMike Christie kfree_skb(skb);
292726974789SMike Christie return -EINVAL;
292826974789SMike Christie }
292953cb8a1fSMike Christie
293053cb8a1fSMike Christie /*
293153cb8a1fSMike Christie * this will occur if the daemon is not up, so we just warn
293253cb8a1fSMike Christie * the user and when the daemon is restarted it will handle it
293353cb8a1fSMike Christie */
293443514774SMichael Chan rc = iscsi_multicast_skb(skb, ISCSI_NL_GRP_ISCSID, GFP_KERNEL);
2935ff491a73SPablo Neira Ayuso if (rc == -ESRCH)
2936322d739dSMike Christie iscsi_cls_session_printk(KERN_ERR, session,
2937322d739dSMike Christie "Cannot notify userspace of session "
2938322d739dSMike Christie "event %u. Check iscsi daemon\n",
2939322d739dSMike Christie event);
2940632248aaSMike Christie
2941632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session, "Completed handling event %d rc %d\n",
2942632248aaSMike Christie event, rc);
294353cb8a1fSMike Christie return rc;
294453cb8a1fSMike Christie }
294526974789SMike Christie EXPORT_SYMBOL_GPL(iscsi_session_event);
294653cb8a1fSMike Christie
29470896b752SAlex Aizman static int
iscsi_if_create_session(struct iscsi_internal * priv,struct iscsi_endpoint * ep,struct iscsi_uevent * ev,pid_t pid,uint32_t initial_cmdsn,uint16_t cmds_max,uint16_t queue_depth)2948d82ff9beSMike Christie iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
29490c70d84bSMike Christie struct iscsi_uevent *ev, pid_t pid,
29500c70d84bSMike Christie uint32_t initial_cmdsn, uint16_t cmds_max,
29510c70d84bSMike Christie uint16_t queue_depth)
29527b8631b5SMike Christie {
29537b8631b5SMike Christie struct iscsi_transport *transport = priv->iscsi_transport;
29547b7232f3SMike Christie struct iscsi_cls_session *session;
29555e7facb7SMike Christie struct Scsi_Host *shost;
29567b8631b5SMike Christie
2957d82ff9beSMike Christie session = transport->create_session(ep, cmds_max, queue_depth,
29585e7facb7SMike Christie initial_cmdsn);
29597b7232f3SMike Christie if (!session)
29607b8631b5SMike Christie return -ENOMEM;
29617b8631b5SMike Christie
29620c70d84bSMike Christie session->creator = pid;
29635e7facb7SMike Christie shost = iscsi_session_to_shost(session);
29645e7facb7SMike Christie ev->r.c_session_ret.host_no = shost->host_no;
2965b5c7a12dSMike Christie ev->r.c_session_ret.sid = session->sid;
2966632248aaSMike Christie ISCSI_DBG_TRANS_SESSION(session,
2967632248aaSMike Christie "Completed creating transport session\n");
29687b8631b5SMike Christie return 0;
29697b8631b5SMike Christie }
29707b8631b5SMike Christie
29717b8631b5SMike Christie static int
iscsi_if_create_conn(struct iscsi_transport * transport,struct iscsi_uevent * ev)29727b7232f3SMike Christie iscsi_if_create_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
29737b8631b5SMike Christie {
29747b8631b5SMike Christie struct iscsi_cls_conn *conn;
29757b7232f3SMike Christie struct iscsi_cls_session *session;
29767b8631b5SMike Christie
2977b5c7a12dSMike Christie session = iscsi_session_lookup(ev->u.c_conn.sid);
2978b5c7a12dSMike Christie if (!session) {
2979322d739dSMike Christie printk(KERN_ERR "iscsi: invalid session %d.\n",
2980b5c7a12dSMike Christie ev->u.c_conn.sid);
29817b8631b5SMike Christie return -EINVAL;
2982b5c7a12dSMike Christie }
29837b8631b5SMike Christie
29847b7232f3SMike Christie conn = transport->create_conn(session, ev->u.c_conn.cid);
2985b5c7a12dSMike Christie if (!conn) {
2986322d739dSMike Christie iscsi_cls_session_printk(KERN_ERR, session,
2987322d739dSMike Christie "couldn't create a new connection.");
29887b7232f3SMike Christie return -ENOMEM;
2989b5c7a12dSMike Christie }
29907b8631b5SMike Christie
2991b5c7a12dSMike Christie ev->r.c_conn_ret.sid = session->sid;
2992b5c7a12dSMike Christie ev->r.c_conn_ret.cid = conn->cid;
2993632248aaSMike Christie
2994632248aaSMike Christie ISCSI_DBG_TRANS_CONN(conn, "Completed creating transport conn\n");
29957b8631b5SMike Christie return 0;
29967b8631b5SMike Christie }
29977b8631b5SMike Christie
29987b8631b5SMike Christie static int
iscsi_if_destroy_conn(struct iscsi_transport * transport,struct iscsi_uevent * ev)29997b8631b5SMike Christie iscsi_if_destroy_conn(struct iscsi_transport *transport, struct iscsi_uevent *ev)
30007b8631b5SMike Christie {
30017b8631b5SMike Christie struct iscsi_cls_conn *conn;
30027b8631b5SMike Christie
3003b5c7a12dSMike Christie conn = iscsi_conn_lookup(ev->u.d_conn.sid, ev->u.d_conn.cid);
30047b8631b5SMike Christie if (!conn)
30057b8631b5SMike Christie return -EINVAL;
30067b8631b5SMike Christie
300723d6fefbSMike Christie ISCSI_DBG_TRANS_CONN(conn, "Flushing cleanup during destruction\n");
300823d6fefbSMike Christie flush_work(&conn->cleanup_work);
3009632248aaSMike Christie ISCSI_DBG_TRANS_CONN(conn, "Destroying transport conn\n");
30107e7cd796SGabriel Krisman Bertazi
30117b8631b5SMike Christie if (transport->destroy_conn)
30127b8631b5SMike Christie transport->destroy_conn(conn);
30137b8631b5SMike Christie return 0;
30147b8631b5SMike Christie }
30157b8631b5SMike Christie
3016fd7255f5SMike Christie static int
iscsi_if_set_param(struct iscsi_transport * transport,struct iscsi_uevent * ev,u32 rlen)3017971dfcb7SLin Ma iscsi_if_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
3018fd7255f5SMike Christie {
3019fd7255f5SMike Christie char *data = (char*)ev + sizeof(*ev);
3020fd7255f5SMike Christie struct iscsi_cls_conn *conn;
3021fd7255f5SMike Christie struct iscsi_cls_session *session;
302203690d81SMike Christie int err = 0, value = 0, state;
3023fd7255f5SMike Christie
3024971dfcb7SLin Ma if (ev->u.set_param.len > rlen ||
3025971dfcb7SLin Ma ev->u.set_param.len > PAGE_SIZE)
3026ec98ea70SChris Leech return -EINVAL;
3027ec98ea70SChris Leech
3028fd7255f5SMike Christie session = iscsi_session_lookup(ev->u.set_param.sid);
3029fd7255f5SMike Christie conn = iscsi_conn_lookup(ev->u.set_param.sid, ev->u.set_param.cid);
3030fd7255f5SMike Christie if (!conn || !session)
3031fd7255f5SMike Christie return -EINVAL;
3032fd7255f5SMike Christie
3033ce51c817SLin Ma /* data will be regarded as NULL-ended string, do length check */
3034ce51c817SLin Ma if (strlen(data) > ev->u.set_param.len)
3035ce51c817SLin Ma return -EINVAL;
3036ce51c817SLin Ma
3037fd7255f5SMike Christie switch (ev->u.set_param.param) {
303830a6c652SMike Christie case ISCSI_PARAM_SESS_RECOVERY_TMO:
3039a54a52caSMike Christie sscanf(data, "%d", &value);
30409c8108a4SChris Leech if (!session->recovery_tmo_sysfs_override)
304130a6c652SMike Christie session->recovery_tmo = value;
304230a6c652SMike Christie break;
3043fd7255f5SMike Christie default:
304403690d81SMike Christie state = READ_ONCE(conn->state);
304503690d81SMike Christie if (state == ISCSI_CONN_BOUND || state == ISCSI_CONN_UP) {
30469e67600eSGulam Mohamed err = transport->set_param(conn, ev->u.set_param.param,
30479e67600eSGulam Mohamed data, ev->u.set_param.len);
30489e67600eSGulam Mohamed } else {
30499e67600eSGulam Mohamed return -ENOTCONN;
30509e67600eSGulam Mohamed }
3051fd7255f5SMike Christie }
3052fd7255f5SMike Christie
3053fd7255f5SMike Christie return err;
3054fd7255f5SMike Christie }
3055fd7255f5SMike Christie
iscsi_if_ep_connect(struct iscsi_transport * transport,struct iscsi_uevent * ev,int msg_type)305610eb0f01SMike Christie static int iscsi_if_ep_connect(struct iscsi_transport *transport,
305710eb0f01SMike Christie struct iscsi_uevent *ev, int msg_type)
305810eb0f01SMike Christie {
305910eb0f01SMike Christie struct iscsi_endpoint *ep;
306010eb0f01SMike Christie struct sockaddr *dst_addr;
306110eb0f01SMike Christie struct Scsi_Host *shost = NULL;
306210eb0f01SMike Christie int non_blocking, err = 0;
306310eb0f01SMike Christie
306410eb0f01SMike Christie if (!transport->ep_connect)
306510eb0f01SMike Christie return -EINVAL;
306610eb0f01SMike Christie
306710eb0f01SMike Christie if (msg_type == ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST) {
306810eb0f01SMike Christie shost = scsi_host_lookup(ev->u.ep_connect_through_host.host_no);
306910eb0f01SMike Christie if (!shost) {
307010eb0f01SMike Christie printk(KERN_ERR "ep connect failed. Could not find "
307110eb0f01SMike Christie "host no %u\n",
307210eb0f01SMike Christie ev->u.ep_connect_through_host.host_no);
307310eb0f01SMike Christie return -ENODEV;
307410eb0f01SMike Christie }
307510eb0f01SMike Christie non_blocking = ev->u.ep_connect_through_host.non_blocking;
307610eb0f01SMike Christie } else
307710eb0f01SMike Christie non_blocking = ev->u.ep_connect.non_blocking;
307810eb0f01SMike Christie
307910eb0f01SMike Christie dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
308010eb0f01SMike Christie ep = transport->ep_connect(shost, dst_addr, non_blocking);
308110eb0f01SMike Christie if (IS_ERR(ep)) {
308210eb0f01SMike Christie err = PTR_ERR(ep);
308310eb0f01SMike Christie goto release_host;
308410eb0f01SMike Christie }
308510eb0f01SMike Christie
308610eb0f01SMike Christie ev->r.ep_connect_ret.handle = ep->id;
308710eb0f01SMike Christie release_host:
308810eb0f01SMike Christie if (shost)
308910eb0f01SMike Christie scsi_host_put(shost);
309010eb0f01SMike Christie return err;
309110eb0f01SMike Christie }
309210eb0f01SMike Christie
iscsi_if_ep_disconnect(struct iscsi_transport * transport,u64 ep_handle)309322a39fbbSMike Christie static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
309423d6fefbSMike Christie u64 ep_handle)
309522a39fbbSMike Christie {
309622a39fbbSMike Christie struct iscsi_cls_conn *conn;
309722a39fbbSMike Christie struct iscsi_endpoint *ep;
309822a39fbbSMike Christie
309922a39fbbSMike Christie if (!transport->ep_disconnect)
310022a39fbbSMike Christie return -EINVAL;
310122a39fbbSMike Christie
310222a39fbbSMike Christie ep = iscsi_lookup_endpoint(ep_handle);
310322a39fbbSMike Christie if (!ep)
310422a39fbbSMike Christie return -EINVAL;
3105891e2639SMike Christie
310623d6fefbSMike Christie conn = ep->conn;
310723d6fefbSMike Christie if (!conn) {
310823d6fefbSMike Christie /*
310923d6fefbSMike Christie * conn was not even bound yet, so we can't get iscsi conn
311023d6fefbSMike Christie * failures yet.
311123d6fefbSMike Christie */
311223d6fefbSMike Christie transport->ep_disconnect(ep);
311323d6fefbSMike Christie goto put_ep;
311422a39fbbSMike Christie }
311522a39fbbSMike Christie
311623d6fefbSMike Christie mutex_lock(&conn->ep_mutex);
3117cbd2283aSMike Christie iscsi_if_disconnect_bound_ep(conn, ep, false);
311823d6fefbSMike Christie mutex_unlock(&conn->ep_mutex);
311923d6fefbSMike Christie put_ep:
31209e5fe170SMike Christie iscsi_put_endpoint(ep);
312122a39fbbSMike Christie return 0;
312222a39fbbSMike Christie }
312322a39fbbSMike Christie
31247b8631b5SMike Christie static int
iscsi_if_transport_ep(struct iscsi_transport * transport,struct iscsi_uevent * ev,int msg_type,u32 rlen)3125264faaaaSOr Gerlitz iscsi_if_transport_ep(struct iscsi_transport *transport,
3126971dfcb7SLin Ma struct iscsi_uevent *ev, int msg_type, u32 rlen)
3127264faaaaSOr Gerlitz {
3128d82ff9beSMike Christie struct iscsi_endpoint *ep;
3129264faaaaSOr Gerlitz int rc = 0;
3130264faaaaSOr Gerlitz
3131264faaaaSOr Gerlitz switch (msg_type) {
313210eb0f01SMike Christie case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
3133264faaaaSOr Gerlitz case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
3134971dfcb7SLin Ma if (rlen < sizeof(struct sockaddr))
3135971dfcb7SLin Ma rc = -EINVAL;
3136971dfcb7SLin Ma else
313710eb0f01SMike Christie rc = iscsi_if_ep_connect(transport, ev, msg_type);
3138264faaaaSOr Gerlitz break;
3139264faaaaSOr Gerlitz case ISCSI_UEVENT_TRANSPORT_EP_POLL:
3140264faaaaSOr Gerlitz if (!transport->ep_poll)
3141264faaaaSOr Gerlitz return -EINVAL;
3142264faaaaSOr Gerlitz
3143d82ff9beSMike Christie ep = iscsi_lookup_endpoint(ev->u.ep_poll.ep_handle);
3144d82ff9beSMike Christie if (!ep)
3145d82ff9beSMike Christie return -EINVAL;
3146d82ff9beSMike Christie
3147d82ff9beSMike Christie ev->r.retcode = transport->ep_poll(ep,
3148264faaaaSOr Gerlitz ev->u.ep_poll.timeout_ms);
31499e5fe170SMike Christie iscsi_put_endpoint(ep);
3150264faaaaSOr Gerlitz break;
3151264faaaaSOr Gerlitz case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
315222a39fbbSMike Christie rc = iscsi_if_ep_disconnect(transport,
315323d6fefbSMike Christie ev->u.ep_disconnect.ep_handle);
3154264faaaaSOr Gerlitz break;
3155264faaaaSOr Gerlitz }
3156264faaaaSOr Gerlitz return rc;
3157264faaaaSOr Gerlitz }
3158264faaaaSOr Gerlitz
3159264faaaaSOr Gerlitz static int
iscsi_tgt_dscvr(struct iscsi_transport * transport,struct iscsi_uevent * ev,u32 rlen)316001cb225dSMike Christie iscsi_tgt_dscvr(struct iscsi_transport *transport,
3161971dfcb7SLin Ma struct iscsi_uevent *ev, u32 rlen)
316201cb225dSMike Christie {
31632174a04eSMike Christie struct Scsi_Host *shost;
316401cb225dSMike Christie struct sockaddr *dst_addr;
31652174a04eSMike Christie int err;
316601cb225dSMike Christie
3167971dfcb7SLin Ma if (rlen < sizeof(*dst_addr))
3168971dfcb7SLin Ma return -EINVAL;
3169971dfcb7SLin Ma
317001cb225dSMike Christie if (!transport->tgt_dscvr)
317101cb225dSMike Christie return -EINVAL;
317201cb225dSMike Christie
31732174a04eSMike Christie shost = scsi_host_lookup(ev->u.tgt_dscvr.host_no);
3174315cb0adSJames Smart if (!shost) {
31752174a04eSMike Christie printk(KERN_ERR "target discovery could not find host no %u\n",
31762174a04eSMike Christie ev->u.tgt_dscvr.host_no);
31772174a04eSMike Christie return -ENODEV;
31782174a04eSMike Christie }
31792174a04eSMike Christie
31802174a04eSMike Christie
318101cb225dSMike Christie dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
31822174a04eSMike Christie err = transport->tgt_dscvr(shost, ev->u.tgt_dscvr.type,
318301cb225dSMike Christie ev->u.tgt_dscvr.enable, dst_addr);
31842174a04eSMike Christie scsi_host_put(shost);
31852174a04eSMike Christie return err;
318601cb225dSMike Christie }
318701cb225dSMike Christie
318801cb225dSMike Christie static int
iscsi_set_host_param(struct iscsi_transport * transport,struct iscsi_uevent * ev,u32 rlen)31891d9bf13aSMike Christie iscsi_set_host_param(struct iscsi_transport *transport,
3190971dfcb7SLin Ma struct iscsi_uevent *ev, u32 rlen)
31911d9bf13aSMike Christie {
31921d9bf13aSMike Christie char *data = (char*)ev + sizeof(*ev);
31931d9bf13aSMike Christie struct Scsi_Host *shost;
31941d9bf13aSMike Christie int err;
31951d9bf13aSMike Christie
31961d9bf13aSMike Christie if (!transport->set_host_param)
31971d9bf13aSMike Christie return -ENOSYS;
31981d9bf13aSMike Christie
3199971dfcb7SLin Ma if (ev->u.set_host_param.len > rlen ||
3200971dfcb7SLin Ma ev->u.set_host_param.len > PAGE_SIZE)
3201ec98ea70SChris Leech return -EINVAL;
3202ec98ea70SChris Leech
32031d9bf13aSMike Christie shost = scsi_host_lookup(ev->u.set_host_param.host_no);
3204315cb0adSJames Smart if (!shost) {
32051d9bf13aSMike Christie printk(KERN_ERR "set_host_param could not find host no %u\n",
32061d9bf13aSMike Christie ev->u.set_host_param.host_no);
32071d9bf13aSMike Christie return -ENODEV;
32081d9bf13aSMike Christie }
32091d9bf13aSMike Christie
3210ce51c817SLin Ma /* see similar check in iscsi_if_set_param() */
3211ce51c817SLin Ma if (strlen(data) > ev->u.set_host_param.len)
3212ce51c817SLin Ma return -EINVAL;
3213ce51c817SLin Ma
32141d9bf13aSMike Christie err = transport->set_host_param(shost, ev->u.set_host_param.param,
32151d9bf13aSMike Christie data, ev->u.set_host_param.len);
32161d9bf13aSMike Christie scsi_host_put(shost);
32171d9bf13aSMike Christie return err;
32181d9bf13aSMike Christie }
32191d9bf13aSMike Christie
32201d9bf13aSMike Christie static int
iscsi_set_path(struct iscsi_transport * transport,struct iscsi_uevent * ev,u32 rlen)3221971dfcb7SLin Ma iscsi_set_path(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
322243514774SMichael Chan {
322343514774SMichael Chan struct Scsi_Host *shost;
322443514774SMichael Chan struct iscsi_path *params;
322543514774SMichael Chan int err;
322643514774SMichael Chan
3227971dfcb7SLin Ma if (rlen < sizeof(*params))
3228971dfcb7SLin Ma return -EINVAL;
3229971dfcb7SLin Ma
323043514774SMichael Chan if (!transport->set_path)
323143514774SMichael Chan return -ENOSYS;
323243514774SMichael Chan
323343514774SMichael Chan shost = scsi_host_lookup(ev->u.set_path.host_no);
323443514774SMichael Chan if (!shost) {
323543514774SMichael Chan printk(KERN_ERR "set path could not find host no %u\n",
323643514774SMichael Chan ev->u.set_path.host_no);
323743514774SMichael Chan return -ENODEV;
323843514774SMichael Chan }
323943514774SMichael Chan
324043514774SMichael Chan params = (struct iscsi_path *)((char *)ev + sizeof(*ev));
324143514774SMichael Chan err = transport->set_path(shost, params);
324243514774SMichael Chan
324343514774SMichael Chan scsi_host_put(shost);
324443514774SMichael Chan return err;
324543514774SMichael Chan }
324643514774SMichael Chan
iscsi_session_has_conns(int sid)324754155ed4SNick Black static int iscsi_session_has_conns(int sid)
324854155ed4SNick Black {
324954155ed4SNick Black struct iscsi_cls_conn *conn;
325054155ed4SNick Black unsigned long flags;
325154155ed4SNick Black int found = 0;
325254155ed4SNick Black
325354155ed4SNick Black spin_lock_irqsave(&connlock, flags);
325454155ed4SNick Black list_for_each_entry(conn, &connlist, conn_list) {
325554155ed4SNick Black if (iscsi_conn_get_sid(conn) == sid) {
325654155ed4SNick Black found = 1;
325754155ed4SNick Black break;
325854155ed4SNick Black }
325954155ed4SNick Black }
326054155ed4SNick Black spin_unlock_irqrestore(&connlock, flags);
326154155ed4SNick Black
326254155ed4SNick Black return found;
326354155ed4SNick Black }
326454155ed4SNick Black
326543514774SMichael Chan static int
iscsi_set_iface_params(struct iscsi_transport * transport,struct iscsi_uevent * ev,uint32_t len)326656c155b5SMike Christie iscsi_set_iface_params(struct iscsi_transport *transport,
326700c31889SMike Christie struct iscsi_uevent *ev, uint32_t len)
326856c155b5SMike Christie {
326956c155b5SMike Christie char *data = (char *)ev + sizeof(*ev);
327056c155b5SMike Christie struct Scsi_Host *shost;
327156c155b5SMike Christie int err;
327256c155b5SMike Christie
327356c155b5SMike Christie if (!transport->set_iface_param)
327456c155b5SMike Christie return -ENOSYS;
327556c155b5SMike Christie
327656c155b5SMike Christie shost = scsi_host_lookup(ev->u.set_iface_params.host_no);
327756c155b5SMike Christie if (!shost) {
327856c155b5SMike Christie printk(KERN_ERR "set_iface_params could not find host no %u\n",
327956c155b5SMike Christie ev->u.set_iface_params.host_no);
328056c155b5SMike Christie return -ENODEV;
328156c155b5SMike Christie }
328256c155b5SMike Christie
328300c31889SMike Christie err = transport->set_iface_param(shost, data, len);
328456c155b5SMike Christie scsi_host_put(shost);
328556c155b5SMike Christie return err;
328656c155b5SMike Christie }
328756c155b5SMike Christie
328856c155b5SMike Christie static int
iscsi_send_ping(struct iscsi_transport * transport,struct iscsi_uevent * ev,u32 rlen)3289971dfcb7SLin Ma iscsi_send_ping(struct iscsi_transport *transport, struct iscsi_uevent *ev, u32 rlen)
3290ac20c7bfSVikas Chaudhary {
3291ac20c7bfSVikas Chaudhary struct Scsi_Host *shost;
3292ac20c7bfSVikas Chaudhary struct sockaddr *dst_addr;
3293ac20c7bfSVikas Chaudhary int err;
3294ac20c7bfSVikas Chaudhary
3295971dfcb7SLin Ma if (rlen < sizeof(*dst_addr))
3296971dfcb7SLin Ma return -EINVAL;
3297971dfcb7SLin Ma
3298ac20c7bfSVikas Chaudhary if (!transport->send_ping)
3299ac20c7bfSVikas Chaudhary return -ENOSYS;
3300ac20c7bfSVikas Chaudhary
3301ac20c7bfSVikas Chaudhary shost = scsi_host_lookup(ev->u.iscsi_ping.host_no);
3302ac20c7bfSVikas Chaudhary if (!shost) {
3303ac20c7bfSVikas Chaudhary printk(KERN_ERR "iscsi_ping could not find host no %u\n",
3304ac20c7bfSVikas Chaudhary ev->u.iscsi_ping.host_no);
3305ac20c7bfSVikas Chaudhary return -ENODEV;
3306ac20c7bfSVikas Chaudhary }
3307ac20c7bfSVikas Chaudhary
3308ac20c7bfSVikas Chaudhary dst_addr = (struct sockaddr *)((char *)ev + sizeof(*ev));
3309ac20c7bfSVikas Chaudhary err = transport->send_ping(shost, ev->u.iscsi_ping.iface_num,
3310ac20c7bfSVikas Chaudhary ev->u.iscsi_ping.iface_type,
3311ac20c7bfSVikas Chaudhary ev->u.iscsi_ping.payload_size,
3312ac20c7bfSVikas Chaudhary ev->u.iscsi_ping.pid,
3313ac20c7bfSVikas Chaudhary dst_addr);
3314ac20c7bfSVikas Chaudhary scsi_host_put(shost);
3315ac20c7bfSVikas Chaudhary return err;
3316ac20c7bfSVikas Chaudhary }
3317ac20c7bfSVikas Chaudhary
3318ac20c7bfSVikas Chaudhary static int
iscsi_get_chap(struct iscsi_transport * transport,struct nlmsghdr * nlh)33196260a5d2SNilesh Javali iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh)
33206260a5d2SNilesh Javali {
3321e07ebea0SHong zhi guo struct iscsi_uevent *ev = nlmsg_data(nlh);
33226260a5d2SNilesh Javali struct Scsi_Host *shost = NULL;
33236260a5d2SNilesh Javali struct iscsi_chap_rec *chap_rec;
33246260a5d2SNilesh Javali struct iscsi_internal *priv;
33256260a5d2SNilesh Javali struct sk_buff *skbchap;
33266260a5d2SNilesh Javali struct nlmsghdr *nlhchap;
33276260a5d2SNilesh Javali struct iscsi_uevent *evchap;
33286260a5d2SNilesh Javali uint32_t chap_buf_size;
33296260a5d2SNilesh Javali int len, err = 0;
33306260a5d2SNilesh Javali char *buf;
33316260a5d2SNilesh Javali
33326260a5d2SNilesh Javali if (!transport->get_chap)
33336260a5d2SNilesh Javali return -EINVAL;
33346260a5d2SNilesh Javali
33356260a5d2SNilesh Javali priv = iscsi_if_transport_lookup(transport);
33366260a5d2SNilesh Javali if (!priv)
33376260a5d2SNilesh Javali return -EINVAL;
33386260a5d2SNilesh Javali
33396260a5d2SNilesh Javali chap_buf_size = (ev->u.get_chap.num_entries * sizeof(*chap_rec));
3340e07ebea0SHong zhi guo len = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
33416260a5d2SNilesh Javali
33426260a5d2SNilesh Javali shost = scsi_host_lookup(ev->u.get_chap.host_no);
33436260a5d2SNilesh Javali if (!shost) {
3344804ff603SMasanari Iida printk(KERN_ERR "%s: failed. Could not find host no %u\n",
33456260a5d2SNilesh Javali __func__, ev->u.get_chap.host_no);
33466260a5d2SNilesh Javali return -ENODEV;
33476260a5d2SNilesh Javali }
33486260a5d2SNilesh Javali
33496260a5d2SNilesh Javali do {
33506260a5d2SNilesh Javali int actual_size;
33516260a5d2SNilesh Javali
33526260a5d2SNilesh Javali skbchap = alloc_skb(len, GFP_KERNEL);
33536260a5d2SNilesh Javali if (!skbchap) {
33546260a5d2SNilesh Javali printk(KERN_ERR "can not deliver chap: OOM\n");
33556260a5d2SNilesh Javali err = -ENOMEM;
33566260a5d2SNilesh Javali goto exit_get_chap;
33576260a5d2SNilesh Javali }
33586260a5d2SNilesh Javali
33596260a5d2SNilesh Javali nlhchap = __nlmsg_put(skbchap, 0, 0, 0,
33606260a5d2SNilesh Javali (len - sizeof(*nlhchap)), 0);
3361e07ebea0SHong zhi guo evchap = nlmsg_data(nlhchap);
33626260a5d2SNilesh Javali memset(evchap, 0, sizeof(*evchap));
33636260a5d2SNilesh Javali evchap->transport_handle = iscsi_handle(transport);
33646260a5d2SNilesh Javali evchap->type = nlh->nlmsg_type;
33656260a5d2SNilesh Javali evchap->u.get_chap.host_no = ev->u.get_chap.host_no;
33666260a5d2SNilesh Javali evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx;
33676260a5d2SNilesh Javali evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries;
3368a799cb77SNick Black' via open-iscsi buf = (char *)evchap + sizeof(*evchap);
33696260a5d2SNilesh Javali memset(buf, 0, chap_buf_size);
33706260a5d2SNilesh Javali
33716260a5d2SNilesh Javali err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx,
33726260a5d2SNilesh Javali &evchap->u.get_chap.num_entries, buf);
33736260a5d2SNilesh Javali
3374e07ebea0SHong zhi guo actual_size = nlmsg_total_size(sizeof(*ev) + chap_buf_size);
33756260a5d2SNilesh Javali skb_trim(skbchap, NLMSG_ALIGN(actual_size));
33766260a5d2SNilesh Javali nlhchap->nlmsg_len = actual_size;
33776260a5d2SNilesh Javali
33786260a5d2SNilesh Javali err = iscsi_multicast_skb(skbchap, ISCSI_NL_GRP_ISCSID,
33796260a5d2SNilesh Javali GFP_KERNEL);
33806260a5d2SNilesh Javali } while (err < 0 && err != -ECONNREFUSED);
33816260a5d2SNilesh Javali
33826260a5d2SNilesh Javali exit_get_chap:
33836260a5d2SNilesh Javali scsi_host_put(shost);
33846260a5d2SNilesh Javali return err;
33856260a5d2SNilesh Javali }
33866260a5d2SNilesh Javali
iscsi_set_chap(struct iscsi_transport * transport,struct iscsi_uevent * ev,uint32_t len)33873af142feSAdheer Chandravanshi static int iscsi_set_chap(struct iscsi_transport *transport,
33883af142feSAdheer Chandravanshi struct iscsi_uevent *ev, uint32_t len)
33893af142feSAdheer Chandravanshi {
33903af142feSAdheer Chandravanshi char *data = (char *)ev + sizeof(*ev);
33913af142feSAdheer Chandravanshi struct Scsi_Host *shost;
33923af142feSAdheer Chandravanshi int err = 0;
33933af142feSAdheer Chandravanshi
33943af142feSAdheer Chandravanshi if (!transport->set_chap)
33953af142feSAdheer Chandravanshi return -ENOSYS;
33963af142feSAdheer Chandravanshi
33973af142feSAdheer Chandravanshi shost = scsi_host_lookup(ev->u.set_path.host_no);
33983af142feSAdheer Chandravanshi if (!shost) {
33993af142feSAdheer Chandravanshi pr_err("%s could not find host no %u\n",
34003af142feSAdheer Chandravanshi __func__, ev->u.set_path.host_no);
34013af142feSAdheer Chandravanshi return -ENODEV;
34023af142feSAdheer Chandravanshi }
34033af142feSAdheer Chandravanshi
34043af142feSAdheer Chandravanshi err = transport->set_chap(shost, data, len);
34053af142feSAdheer Chandravanshi scsi_host_put(shost);
34063af142feSAdheer Chandravanshi return err;
34073af142feSAdheer Chandravanshi }
34083af142feSAdheer Chandravanshi
iscsi_delete_chap(struct iscsi_transport * transport,struct iscsi_uevent * ev)34096260a5d2SNilesh Javali static int iscsi_delete_chap(struct iscsi_transport *transport,
34106260a5d2SNilesh Javali struct iscsi_uevent *ev)
34116260a5d2SNilesh Javali {
34126260a5d2SNilesh Javali struct Scsi_Host *shost;
34136260a5d2SNilesh Javali int err = 0;
34146260a5d2SNilesh Javali
34156260a5d2SNilesh Javali if (!transport->delete_chap)
34166260a5d2SNilesh Javali return -ENOSYS;
34176260a5d2SNilesh Javali
34186260a5d2SNilesh Javali shost = scsi_host_lookup(ev->u.delete_chap.host_no);
34196260a5d2SNilesh Javali if (!shost) {
34206260a5d2SNilesh Javali printk(KERN_ERR "%s could not find host no %u\n",
34216260a5d2SNilesh Javali __func__, ev->u.delete_chap.host_no);
34226260a5d2SNilesh Javali return -ENODEV;
34236260a5d2SNilesh Javali }
34246260a5d2SNilesh Javali
34256260a5d2SNilesh Javali err = transport->delete_chap(shost, ev->u.delete_chap.chap_tbl_idx);
34266260a5d2SNilesh Javali scsi_host_put(shost);
34276260a5d2SNilesh Javali return err;
34286260a5d2SNilesh Javali }
34296260a5d2SNilesh Javali
3430c6a4bb2eSAdheer Chandravanshi static const struct {
3431c6a4bb2eSAdheer Chandravanshi enum iscsi_discovery_parent_type value;
3432c6a4bb2eSAdheer Chandravanshi char *name;
3433c6a4bb2eSAdheer Chandravanshi } iscsi_discovery_parent_names[] = {
3434c6a4bb2eSAdheer Chandravanshi {ISCSI_DISC_PARENT_UNKNOWN, "Unknown" },
3435c6a4bb2eSAdheer Chandravanshi {ISCSI_DISC_PARENT_SENDTGT, "Sendtarget" },
3436c6a4bb2eSAdheer Chandravanshi {ISCSI_DISC_PARENT_ISNS, "isns" },
3437c6a4bb2eSAdheer Chandravanshi };
3438c6a4bb2eSAdheer Chandravanshi
iscsi_get_discovery_parent_name(int parent_type)3439c6a4bb2eSAdheer Chandravanshi char *iscsi_get_discovery_parent_name(int parent_type)
3440c6a4bb2eSAdheer Chandravanshi {
3441c6a4bb2eSAdheer Chandravanshi int i;
3442c6a4bb2eSAdheer Chandravanshi char *state = "Unknown!";
3443c6a4bb2eSAdheer Chandravanshi
3444c6a4bb2eSAdheer Chandravanshi for (i = 0; i < ARRAY_SIZE(iscsi_discovery_parent_names); i++) {
3445c6a4bb2eSAdheer Chandravanshi if (iscsi_discovery_parent_names[i].value & parent_type) {
3446c6a4bb2eSAdheer Chandravanshi state = iscsi_discovery_parent_names[i].name;
3447c6a4bb2eSAdheer Chandravanshi break;
3448c6a4bb2eSAdheer Chandravanshi }
3449c6a4bb2eSAdheer Chandravanshi }
3450c6a4bb2eSAdheer Chandravanshi return state;
3451c6a4bb2eSAdheer Chandravanshi }
3452c6a4bb2eSAdheer Chandravanshi EXPORT_SYMBOL_GPL(iscsi_get_discovery_parent_name);
3453c6a4bb2eSAdheer Chandravanshi
iscsi_set_flashnode_param(struct iscsi_transport * transport,struct iscsi_uevent * ev,uint32_t len)3454c6a4bb2eSAdheer Chandravanshi static int iscsi_set_flashnode_param(struct iscsi_transport *transport,
3455c6a4bb2eSAdheer Chandravanshi struct iscsi_uevent *ev, uint32_t len)
3456c6a4bb2eSAdheer Chandravanshi {
3457c6a4bb2eSAdheer Chandravanshi char *data = (char *)ev + sizeof(*ev);
3458c6a4bb2eSAdheer Chandravanshi struct Scsi_Host *shost;
3459c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess;
3460c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_conn *fnode_conn;
3461c6a4bb2eSAdheer Chandravanshi struct device *dev;
34628526cb11SMike Christie uint32_t idx;
3463c6a4bb2eSAdheer Chandravanshi int err = 0;
3464c6a4bb2eSAdheer Chandravanshi
3465c6a4bb2eSAdheer Chandravanshi if (!transport->set_flashnode_param) {
3466c6a4bb2eSAdheer Chandravanshi err = -ENOSYS;
3467c6a4bb2eSAdheer Chandravanshi goto exit_set_fnode;
3468c6a4bb2eSAdheer Chandravanshi }
3469c6a4bb2eSAdheer Chandravanshi
3470c6a4bb2eSAdheer Chandravanshi shost = scsi_host_lookup(ev->u.set_flashnode.host_no);
3471c6a4bb2eSAdheer Chandravanshi if (!shost) {
3472c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find host no %u\n",
3473c6a4bb2eSAdheer Chandravanshi __func__, ev->u.set_flashnode.host_no);
3474c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
347568e12e5fSJing Xiangfeng goto exit_set_fnode;
3476c6a4bb2eSAdheer Chandravanshi }
3477c6a4bb2eSAdheer Chandravanshi
34788526cb11SMike Christie idx = ev->u.set_flashnode.flashnode_idx;
34798526cb11SMike Christie fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
3480c6a4bb2eSAdheer Chandravanshi if (!fnode_sess) {
3481c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find flashnode %u for host no %u\n",
34828526cb11SMike Christie __func__, idx, ev->u.set_flashnode.host_no);
3483c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
3484c6a4bb2eSAdheer Chandravanshi goto put_host;
3485c6a4bb2eSAdheer Chandravanshi }
3486c6a4bb2eSAdheer Chandravanshi
34878526cb11SMike Christie dev = iscsi_find_flashnode_conn(fnode_sess);
3488c6a4bb2eSAdheer Chandravanshi if (!dev) {
3489c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
34908526cb11SMike Christie goto put_sess;
3491c6a4bb2eSAdheer Chandravanshi }
3492c6a4bb2eSAdheer Chandravanshi
3493c6a4bb2eSAdheer Chandravanshi fnode_conn = iscsi_dev_to_flash_conn(dev);
3494c6a4bb2eSAdheer Chandravanshi err = transport->set_flashnode_param(fnode_sess, fnode_conn, data, len);
34958526cb11SMike Christie put_device(dev);
34968526cb11SMike Christie
34978526cb11SMike Christie put_sess:
34988526cb11SMike Christie put_device(&fnode_sess->dev);
3499c6a4bb2eSAdheer Chandravanshi
3500c6a4bb2eSAdheer Chandravanshi put_host:
3501c6a4bb2eSAdheer Chandravanshi scsi_host_put(shost);
3502c6a4bb2eSAdheer Chandravanshi
3503c6a4bb2eSAdheer Chandravanshi exit_set_fnode:
3504c6a4bb2eSAdheer Chandravanshi return err;
3505c6a4bb2eSAdheer Chandravanshi }
3506c6a4bb2eSAdheer Chandravanshi
iscsi_new_flashnode(struct iscsi_transport * transport,struct iscsi_uevent * ev,uint32_t len)3507c6a4bb2eSAdheer Chandravanshi static int iscsi_new_flashnode(struct iscsi_transport *transport,
3508c6a4bb2eSAdheer Chandravanshi struct iscsi_uevent *ev, uint32_t len)
3509c6a4bb2eSAdheer Chandravanshi {
3510c6a4bb2eSAdheer Chandravanshi char *data = (char *)ev + sizeof(*ev);
3511c6a4bb2eSAdheer Chandravanshi struct Scsi_Host *shost;
3512c6a4bb2eSAdheer Chandravanshi int index;
3513c6a4bb2eSAdheer Chandravanshi int err = 0;
3514c6a4bb2eSAdheer Chandravanshi
3515c6a4bb2eSAdheer Chandravanshi if (!transport->new_flashnode) {
3516c6a4bb2eSAdheer Chandravanshi err = -ENOSYS;
3517c6a4bb2eSAdheer Chandravanshi goto exit_new_fnode;
3518c6a4bb2eSAdheer Chandravanshi }
3519c6a4bb2eSAdheer Chandravanshi
3520c6a4bb2eSAdheer Chandravanshi shost = scsi_host_lookup(ev->u.new_flashnode.host_no);
3521c6a4bb2eSAdheer Chandravanshi if (!shost) {
3522c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find host no %u\n",
3523c6a4bb2eSAdheer Chandravanshi __func__, ev->u.new_flashnode.host_no);
3524c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
3525c6a4bb2eSAdheer Chandravanshi goto put_host;
3526c6a4bb2eSAdheer Chandravanshi }
3527c6a4bb2eSAdheer Chandravanshi
3528c6a4bb2eSAdheer Chandravanshi index = transport->new_flashnode(shost, data, len);
3529c6a4bb2eSAdheer Chandravanshi
3530c6a4bb2eSAdheer Chandravanshi if (index >= 0)
3531c6a4bb2eSAdheer Chandravanshi ev->r.new_flashnode_ret.flashnode_idx = index;
3532c6a4bb2eSAdheer Chandravanshi else
3533c6a4bb2eSAdheer Chandravanshi err = -EIO;
3534c6a4bb2eSAdheer Chandravanshi
3535c6a4bb2eSAdheer Chandravanshi put_host:
3536c6a4bb2eSAdheer Chandravanshi scsi_host_put(shost);
3537c6a4bb2eSAdheer Chandravanshi
3538c6a4bb2eSAdheer Chandravanshi exit_new_fnode:
3539c6a4bb2eSAdheer Chandravanshi return err;
3540c6a4bb2eSAdheer Chandravanshi }
3541c6a4bb2eSAdheer Chandravanshi
iscsi_del_flashnode(struct iscsi_transport * transport,struct iscsi_uevent * ev)3542c6a4bb2eSAdheer Chandravanshi static int iscsi_del_flashnode(struct iscsi_transport *transport,
3543c6a4bb2eSAdheer Chandravanshi struct iscsi_uevent *ev)
3544c6a4bb2eSAdheer Chandravanshi {
3545c6a4bb2eSAdheer Chandravanshi struct Scsi_Host *shost;
3546c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess;
35478526cb11SMike Christie uint32_t idx;
3548c6a4bb2eSAdheer Chandravanshi int err = 0;
3549c6a4bb2eSAdheer Chandravanshi
3550c6a4bb2eSAdheer Chandravanshi if (!transport->del_flashnode) {
3551c6a4bb2eSAdheer Chandravanshi err = -ENOSYS;
3552c6a4bb2eSAdheer Chandravanshi goto exit_del_fnode;
3553c6a4bb2eSAdheer Chandravanshi }
3554c6a4bb2eSAdheer Chandravanshi
3555c6a4bb2eSAdheer Chandravanshi shost = scsi_host_lookup(ev->u.del_flashnode.host_no);
3556c6a4bb2eSAdheer Chandravanshi if (!shost) {
3557c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find host no %u\n",
3558c6a4bb2eSAdheer Chandravanshi __func__, ev->u.del_flashnode.host_no);
3559c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
3560c6a4bb2eSAdheer Chandravanshi goto put_host;
3561c6a4bb2eSAdheer Chandravanshi }
3562c6a4bb2eSAdheer Chandravanshi
35638526cb11SMike Christie idx = ev->u.del_flashnode.flashnode_idx;
35648526cb11SMike Christie fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
3565c6a4bb2eSAdheer Chandravanshi if (!fnode_sess) {
3566c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find flashnode %u for host no %u\n",
35678526cb11SMike Christie __func__, idx, ev->u.del_flashnode.host_no);
3568c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
3569c6a4bb2eSAdheer Chandravanshi goto put_host;
3570c6a4bb2eSAdheer Chandravanshi }
3571c6a4bb2eSAdheer Chandravanshi
3572c6a4bb2eSAdheer Chandravanshi err = transport->del_flashnode(fnode_sess);
35738526cb11SMike Christie put_device(&fnode_sess->dev);
3574c6a4bb2eSAdheer Chandravanshi
3575c6a4bb2eSAdheer Chandravanshi put_host:
3576c6a4bb2eSAdheer Chandravanshi scsi_host_put(shost);
3577c6a4bb2eSAdheer Chandravanshi
3578c6a4bb2eSAdheer Chandravanshi exit_del_fnode:
3579c6a4bb2eSAdheer Chandravanshi return err;
3580c6a4bb2eSAdheer Chandravanshi }
3581c6a4bb2eSAdheer Chandravanshi
iscsi_login_flashnode(struct iscsi_transport * transport,struct iscsi_uevent * ev)3582c6a4bb2eSAdheer Chandravanshi static int iscsi_login_flashnode(struct iscsi_transport *transport,
3583c6a4bb2eSAdheer Chandravanshi struct iscsi_uevent *ev)
3584c6a4bb2eSAdheer Chandravanshi {
3585c6a4bb2eSAdheer Chandravanshi struct Scsi_Host *shost;
3586c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess;
3587c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_conn *fnode_conn;
3588c6a4bb2eSAdheer Chandravanshi struct device *dev;
35898526cb11SMike Christie uint32_t idx;
3590c6a4bb2eSAdheer Chandravanshi int err = 0;
3591c6a4bb2eSAdheer Chandravanshi
3592c6a4bb2eSAdheer Chandravanshi if (!transport->login_flashnode) {
3593c6a4bb2eSAdheer Chandravanshi err = -ENOSYS;
3594c6a4bb2eSAdheer Chandravanshi goto exit_login_fnode;
3595c6a4bb2eSAdheer Chandravanshi }
3596c6a4bb2eSAdheer Chandravanshi
3597c6a4bb2eSAdheer Chandravanshi shost = scsi_host_lookup(ev->u.login_flashnode.host_no);
3598c6a4bb2eSAdheer Chandravanshi if (!shost) {
3599c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find host no %u\n",
3600c6a4bb2eSAdheer Chandravanshi __func__, ev->u.login_flashnode.host_no);
3601c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
3602c6a4bb2eSAdheer Chandravanshi goto put_host;
3603c6a4bb2eSAdheer Chandravanshi }
3604c6a4bb2eSAdheer Chandravanshi
36058526cb11SMike Christie idx = ev->u.login_flashnode.flashnode_idx;
36068526cb11SMike Christie fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
3607c6a4bb2eSAdheer Chandravanshi if (!fnode_sess) {
3608c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find flashnode %u for host no %u\n",
36098526cb11SMike Christie __func__, idx, ev->u.login_flashnode.host_no);
3610c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
3611c6a4bb2eSAdheer Chandravanshi goto put_host;
3612c6a4bb2eSAdheer Chandravanshi }
3613c6a4bb2eSAdheer Chandravanshi
36148526cb11SMike Christie dev = iscsi_find_flashnode_conn(fnode_sess);
3615c6a4bb2eSAdheer Chandravanshi if (!dev) {
3616c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
36178526cb11SMike Christie goto put_sess;
3618c6a4bb2eSAdheer Chandravanshi }
3619c6a4bb2eSAdheer Chandravanshi
3620c6a4bb2eSAdheer Chandravanshi fnode_conn = iscsi_dev_to_flash_conn(dev);
3621c6a4bb2eSAdheer Chandravanshi err = transport->login_flashnode(fnode_sess, fnode_conn);
36228526cb11SMike Christie put_device(dev);
36238526cb11SMike Christie
36248526cb11SMike Christie put_sess:
36258526cb11SMike Christie put_device(&fnode_sess->dev);
3626c6a4bb2eSAdheer Chandravanshi
3627c6a4bb2eSAdheer Chandravanshi put_host:
3628c6a4bb2eSAdheer Chandravanshi scsi_host_put(shost);
3629c6a4bb2eSAdheer Chandravanshi
3630c6a4bb2eSAdheer Chandravanshi exit_login_fnode:
3631c6a4bb2eSAdheer Chandravanshi return err;
3632c6a4bb2eSAdheer Chandravanshi }
3633c6a4bb2eSAdheer Chandravanshi
iscsi_logout_flashnode(struct iscsi_transport * transport,struct iscsi_uevent * ev)3634c6a4bb2eSAdheer Chandravanshi static int iscsi_logout_flashnode(struct iscsi_transport *transport,
3635c6a4bb2eSAdheer Chandravanshi struct iscsi_uevent *ev)
3636c6a4bb2eSAdheer Chandravanshi {
3637c6a4bb2eSAdheer Chandravanshi struct Scsi_Host *shost;
3638c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_session *fnode_sess;
3639c6a4bb2eSAdheer Chandravanshi struct iscsi_bus_flash_conn *fnode_conn;
3640c6a4bb2eSAdheer Chandravanshi struct device *dev;
36418526cb11SMike Christie uint32_t idx;
3642c6a4bb2eSAdheer Chandravanshi int err = 0;
3643c6a4bb2eSAdheer Chandravanshi
3644c6a4bb2eSAdheer Chandravanshi if (!transport->logout_flashnode) {
3645c6a4bb2eSAdheer Chandravanshi err = -ENOSYS;
3646c6a4bb2eSAdheer Chandravanshi goto exit_logout_fnode;
3647c6a4bb2eSAdheer Chandravanshi }
3648c6a4bb2eSAdheer Chandravanshi
3649c6a4bb2eSAdheer Chandravanshi shost = scsi_host_lookup(ev->u.logout_flashnode.host_no);
3650c6a4bb2eSAdheer Chandravanshi if (!shost) {
3651c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find host no %u\n",
3652c6a4bb2eSAdheer Chandravanshi __func__, ev->u.logout_flashnode.host_no);
3653c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
3654c6a4bb2eSAdheer Chandravanshi goto put_host;
3655c6a4bb2eSAdheer Chandravanshi }
3656c6a4bb2eSAdheer Chandravanshi
36578526cb11SMike Christie idx = ev->u.logout_flashnode.flashnode_idx;
36588526cb11SMike Christie fnode_sess = iscsi_get_flashnode_by_index(shost, idx);
3659c6a4bb2eSAdheer Chandravanshi if (!fnode_sess) {
3660c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find flashnode %u for host no %u\n",
36618526cb11SMike Christie __func__, idx, ev->u.logout_flashnode.host_no);
3662c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
3663c6a4bb2eSAdheer Chandravanshi goto put_host;
3664c6a4bb2eSAdheer Chandravanshi }
3665c6a4bb2eSAdheer Chandravanshi
36668526cb11SMike Christie dev = iscsi_find_flashnode_conn(fnode_sess);
3667c6a4bb2eSAdheer Chandravanshi if (!dev) {
3668c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
36698526cb11SMike Christie goto put_sess;
3670c6a4bb2eSAdheer Chandravanshi }
3671c6a4bb2eSAdheer Chandravanshi
3672c6a4bb2eSAdheer Chandravanshi fnode_conn = iscsi_dev_to_flash_conn(dev);
3673c6a4bb2eSAdheer Chandravanshi
3674c6a4bb2eSAdheer Chandravanshi err = transport->logout_flashnode(fnode_sess, fnode_conn);
36758526cb11SMike Christie put_device(dev);
36768526cb11SMike Christie
36778526cb11SMike Christie put_sess:
36788526cb11SMike Christie put_device(&fnode_sess->dev);
3679c6a4bb2eSAdheer Chandravanshi
3680c6a4bb2eSAdheer Chandravanshi put_host:
3681c6a4bb2eSAdheer Chandravanshi scsi_host_put(shost);
3682c6a4bb2eSAdheer Chandravanshi
3683c6a4bb2eSAdheer Chandravanshi exit_logout_fnode:
3684c6a4bb2eSAdheer Chandravanshi return err;
3685c6a4bb2eSAdheer Chandravanshi }
3686c6a4bb2eSAdheer Chandravanshi
iscsi_logout_flashnode_sid(struct iscsi_transport * transport,struct iscsi_uevent * ev)3687c6a4bb2eSAdheer Chandravanshi static int iscsi_logout_flashnode_sid(struct iscsi_transport *transport,
3688c6a4bb2eSAdheer Chandravanshi struct iscsi_uevent *ev)
3689c6a4bb2eSAdheer Chandravanshi {
3690c6a4bb2eSAdheer Chandravanshi struct Scsi_Host *shost;
3691c6a4bb2eSAdheer Chandravanshi struct iscsi_cls_session *session;
3692c6a4bb2eSAdheer Chandravanshi int err = 0;
3693c6a4bb2eSAdheer Chandravanshi
3694c6a4bb2eSAdheer Chandravanshi if (!transport->logout_flashnode_sid) {
3695c6a4bb2eSAdheer Chandravanshi err = -ENOSYS;
3696c6a4bb2eSAdheer Chandravanshi goto exit_logout_sid;
3697c6a4bb2eSAdheer Chandravanshi }
3698c6a4bb2eSAdheer Chandravanshi
3699c6a4bb2eSAdheer Chandravanshi shost = scsi_host_lookup(ev->u.logout_flashnode_sid.host_no);
3700c6a4bb2eSAdheer Chandravanshi if (!shost) {
3701c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find host no %u\n",
3702c6a4bb2eSAdheer Chandravanshi __func__, ev->u.logout_flashnode.host_no);
3703c6a4bb2eSAdheer Chandravanshi err = -ENODEV;
3704c6a4bb2eSAdheer Chandravanshi goto put_host;
3705c6a4bb2eSAdheer Chandravanshi }
3706c6a4bb2eSAdheer Chandravanshi
3707c6a4bb2eSAdheer Chandravanshi session = iscsi_session_lookup(ev->u.logout_flashnode_sid.sid);
3708c6a4bb2eSAdheer Chandravanshi if (!session) {
3709c6a4bb2eSAdheer Chandravanshi pr_err("%s could not find session id %u\n",
3710c6a4bb2eSAdheer Chandravanshi __func__, ev->u.logout_flashnode_sid.sid);
3711c6a4bb2eSAdheer Chandravanshi err = -EINVAL;
3712c6a4bb2eSAdheer Chandravanshi goto put_host;
3713c6a4bb2eSAdheer Chandravanshi }
3714c6a4bb2eSAdheer Chandravanshi
3715c6a4bb2eSAdheer Chandravanshi err = transport->logout_flashnode_sid(session);
3716c6a4bb2eSAdheer Chandravanshi
3717c6a4bb2eSAdheer Chandravanshi put_host:
3718c6a4bb2eSAdheer Chandravanshi scsi_host_put(shost);
3719c6a4bb2eSAdheer Chandravanshi
3720c6a4bb2eSAdheer Chandravanshi exit_logout_sid:
3721c6a4bb2eSAdheer Chandravanshi return err;
3722c6a4bb2eSAdheer Chandravanshi }
3723c6a4bb2eSAdheer Chandravanshi
37246260a5d2SNilesh Javali static int
iscsi_get_host_stats(struct iscsi_transport * transport,struct nlmsghdr * nlh)37256fa7c554SLalit Chandivade iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh)
37266fa7c554SLalit Chandivade {
37276fa7c554SLalit Chandivade struct iscsi_uevent *ev = nlmsg_data(nlh);
37286fa7c554SLalit Chandivade struct Scsi_Host *shost = NULL;
37296fa7c554SLalit Chandivade struct iscsi_internal *priv;
37306fa7c554SLalit Chandivade struct sk_buff *skbhost_stats;
37316fa7c554SLalit Chandivade struct nlmsghdr *nlhhost_stats;
37326fa7c554SLalit Chandivade struct iscsi_uevent *evhost_stats;
37336fa7c554SLalit Chandivade int host_stats_size = 0;
37346fa7c554SLalit Chandivade int len, err = 0;
37356fa7c554SLalit Chandivade char *buf;
37366fa7c554SLalit Chandivade
37376fa7c554SLalit Chandivade if (!transport->get_host_stats)
3738719e5874SMike Christie return -ENOSYS;
37396fa7c554SLalit Chandivade
37406fa7c554SLalit Chandivade priv = iscsi_if_transport_lookup(transport);
37416fa7c554SLalit Chandivade if (!priv)
37426fa7c554SLalit Chandivade return -EINVAL;
37436fa7c554SLalit Chandivade
37446fa7c554SLalit Chandivade host_stats_size = sizeof(struct iscsi_offload_host_stats);
37456fa7c554SLalit Chandivade len = nlmsg_total_size(sizeof(*ev) + host_stats_size);
37466fa7c554SLalit Chandivade
37476fa7c554SLalit Chandivade shost = scsi_host_lookup(ev->u.get_host_stats.host_no);
37486fa7c554SLalit Chandivade if (!shost) {
3749013ee633SArvind Yadav pr_err("%s: failed. Could not find host no %u\n",
37506fa7c554SLalit Chandivade __func__, ev->u.get_host_stats.host_no);
37516fa7c554SLalit Chandivade return -ENODEV;
37526fa7c554SLalit Chandivade }
37536fa7c554SLalit Chandivade
37546fa7c554SLalit Chandivade do {
37556fa7c554SLalit Chandivade int actual_size;
37566fa7c554SLalit Chandivade
37576fa7c554SLalit Chandivade skbhost_stats = alloc_skb(len, GFP_KERNEL);
37586fa7c554SLalit Chandivade if (!skbhost_stats) {
37596fa7c554SLalit Chandivade pr_err("cannot deliver host stats: OOM\n");
37606fa7c554SLalit Chandivade err = -ENOMEM;
37616fa7c554SLalit Chandivade goto exit_host_stats;
37626fa7c554SLalit Chandivade }
37636fa7c554SLalit Chandivade
37646fa7c554SLalit Chandivade nlhhost_stats = __nlmsg_put(skbhost_stats, 0, 0, 0,
37656fa7c554SLalit Chandivade (len - sizeof(*nlhhost_stats)), 0);
37666fa7c554SLalit Chandivade evhost_stats = nlmsg_data(nlhhost_stats);
37676fa7c554SLalit Chandivade memset(evhost_stats, 0, sizeof(*evhost_stats));
37686fa7c554SLalit Chandivade evhost_stats->transport_handle = iscsi_handle(transport);
37696fa7c554SLalit Chandivade evhost_stats->type = nlh->nlmsg_type;
37706fa7c554SLalit Chandivade evhost_stats->u.get_host_stats.host_no =
37716fa7c554SLalit Chandivade ev->u.get_host_stats.host_no;
3772a799cb77SNick Black' via open-iscsi buf = (char *)evhost_stats + sizeof(*evhost_stats);
37736fa7c554SLalit Chandivade memset(buf, 0, host_stats_size);
37746fa7c554SLalit Chandivade
37756fa7c554SLalit Chandivade err = transport->get_host_stats(shost, buf, host_stats_size);
37762f7608fcSMike Christie if (err) {
3777bfb50879SMike Christie kfree_skb(skbhost_stats);
37782f7608fcSMike Christie goto exit_host_stats;
37792f7608fcSMike Christie }
37806fa7c554SLalit Chandivade
37816fa7c554SLalit Chandivade actual_size = nlmsg_total_size(sizeof(*ev) + host_stats_size);
37826fa7c554SLalit Chandivade skb_trim(skbhost_stats, NLMSG_ALIGN(actual_size));
37836fa7c554SLalit Chandivade nlhhost_stats->nlmsg_len = actual_size;
37846fa7c554SLalit Chandivade
37856fa7c554SLalit Chandivade err = iscsi_multicast_skb(skbhost_stats, ISCSI_NL_GRP_ISCSID,
37866fa7c554SLalit Chandivade GFP_KERNEL);
37876fa7c554SLalit Chandivade } while (err < 0 && err != -ECONNREFUSED);
37886fa7c554SLalit Chandivade
37896fa7c554SLalit Chandivade exit_host_stats:
37906fa7c554SLalit Chandivade scsi_host_put(shost);
37916fa7c554SLalit Chandivade return err;
37926fa7c554SLalit Chandivade }
37936fa7c554SLalit Chandivade
iscsi_if_transport_conn(struct iscsi_transport * transport,struct nlmsghdr * nlh,u32 pdu_len)379423d6fefbSMike Christie static int iscsi_if_transport_conn(struct iscsi_transport *transport,
3795971dfcb7SLin Ma struct nlmsghdr *nlh, u32 pdu_len)
379623d6fefbSMike Christie {
379723d6fefbSMike Christie struct iscsi_uevent *ev = nlmsg_data(nlh);
379823d6fefbSMike Christie struct iscsi_cls_session *session;
379923d6fefbSMike Christie struct iscsi_cls_conn *conn = NULL;
380023d6fefbSMike Christie struct iscsi_endpoint *ep;
380123d6fefbSMike Christie int err = 0;
380223d6fefbSMike Christie
380323d6fefbSMike Christie switch (nlh->nlmsg_type) {
380423d6fefbSMike Christie case ISCSI_UEVENT_CREATE_CONN:
380523d6fefbSMike Christie return iscsi_if_create_conn(transport, ev);
380623d6fefbSMike Christie case ISCSI_UEVENT_DESTROY_CONN:
380723d6fefbSMike Christie return iscsi_if_destroy_conn(transport, ev);
380823d6fefbSMike Christie case ISCSI_UEVENT_STOP_CONN:
38093328333bSMike Christie conn = iscsi_conn_lookup(ev->u.stop_conn.sid,
38103328333bSMike Christie ev->u.stop_conn.cid);
38113328333bSMike Christie if (!conn)
38123328333bSMike Christie return -EINVAL;
38133328333bSMike Christie
38143328333bSMike Christie return iscsi_if_stop_conn(conn, ev->u.stop_conn.flag);
381523d6fefbSMike Christie }
381623d6fefbSMike Christie
381723d6fefbSMike Christie /*
381823d6fefbSMike Christie * The following cmds need to be run under the ep_mutex so in kernel
381923d6fefbSMike Christie * conn cleanup (ep_disconnect + unbind and conn) is not done while
382023d6fefbSMike Christie * these are running. They also must not run if we have just run a conn
382123d6fefbSMike Christie * cleanup because they would set the state in a way that might allow
382223d6fefbSMike Christie * IO or send IO themselves.
382323d6fefbSMike Christie */
382423d6fefbSMike Christie switch (nlh->nlmsg_type) {
382523d6fefbSMike Christie case ISCSI_UEVENT_START_CONN:
382623d6fefbSMike Christie conn = iscsi_conn_lookup(ev->u.start_conn.sid,
382723d6fefbSMike Christie ev->u.start_conn.cid);
382823d6fefbSMike Christie break;
382923d6fefbSMike Christie case ISCSI_UEVENT_BIND_CONN:
383023d6fefbSMike Christie conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
383123d6fefbSMike Christie break;
383223d6fefbSMike Christie case ISCSI_UEVENT_SEND_PDU:
383323d6fefbSMike Christie conn = iscsi_conn_lookup(ev->u.send_pdu.sid, ev->u.send_pdu.cid);
383423d6fefbSMike Christie break;
383523d6fefbSMike Christie }
383623d6fefbSMike Christie
383723d6fefbSMike Christie if (!conn)
383823d6fefbSMike Christie return -EINVAL;
383923d6fefbSMike Christie
384023d6fefbSMike Christie mutex_lock(&conn->ep_mutex);
38417c6e99c1SMike Christie spin_lock_irq(&conn->lock);
384223d6fefbSMike Christie if (test_bit(ISCSI_CLS_CONN_BIT_CLEANUP, &conn->flags)) {
38437c6e99c1SMike Christie spin_unlock_irq(&conn->lock);
384423d6fefbSMike Christie mutex_unlock(&conn->ep_mutex);
384523d6fefbSMike Christie ev->r.retcode = -ENOTCONN;
384623d6fefbSMike Christie return 0;
384723d6fefbSMike Christie }
38487c6e99c1SMike Christie spin_unlock_irq(&conn->lock);
384923d6fefbSMike Christie
385023d6fefbSMike Christie switch (nlh->nlmsg_type) {
385123d6fefbSMike Christie case ISCSI_UEVENT_BIND_CONN:
385223d6fefbSMike Christie session = iscsi_session_lookup(ev->u.b_conn.sid);
385323d6fefbSMike Christie if (!session) {
385423d6fefbSMike Christie err = -EINVAL;
385523d6fefbSMike Christie break;
385623d6fefbSMike Christie }
385723d6fefbSMike Christie
385823d6fefbSMike Christie ev->r.retcode = transport->bind_conn(session, conn,
385923d6fefbSMike Christie ev->u.b_conn.transport_eph,
386023d6fefbSMike Christie ev->u.b_conn.is_leading);
386123d6fefbSMike Christie if (!ev->r.retcode)
386203690d81SMike Christie WRITE_ONCE(conn->state, ISCSI_CONN_BOUND);
386323d6fefbSMike Christie
386423d6fefbSMike Christie if (ev->r.retcode || !transport->ep_connect)
386523d6fefbSMike Christie break;
386623d6fefbSMike Christie
386723d6fefbSMike Christie ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
386823d6fefbSMike Christie if (ep) {
386923d6fefbSMike Christie ep->conn = conn;
387023d6fefbSMike Christie conn->ep = ep;
387123d6fefbSMike Christie iscsi_put_endpoint(ep);
387223d6fefbSMike Christie } else {
387323d6fefbSMike Christie err = -ENOTCONN;
387423d6fefbSMike Christie iscsi_cls_conn_printk(KERN_ERR, conn,
387523d6fefbSMike Christie "Could not set ep conn binding\n");
387623d6fefbSMike Christie }
387723d6fefbSMike Christie break;
387823d6fefbSMike Christie case ISCSI_UEVENT_START_CONN:
387923d6fefbSMike Christie ev->r.retcode = transport->start_conn(conn);
388023d6fefbSMike Christie if (!ev->r.retcode)
388103690d81SMike Christie WRITE_ONCE(conn->state, ISCSI_CONN_UP);
388203690d81SMike Christie
388323d6fefbSMike Christie break;
388423d6fefbSMike Christie case ISCSI_UEVENT_SEND_PDU:
388523d6fefbSMike Christie if ((ev->u.send_pdu.hdr_size > pdu_len) ||
388623d6fefbSMike Christie (ev->u.send_pdu.data_size > (pdu_len - ev->u.send_pdu.hdr_size))) {
388723d6fefbSMike Christie err = -EINVAL;
388823d6fefbSMike Christie break;
388923d6fefbSMike Christie }
389023d6fefbSMike Christie
389123d6fefbSMike Christie ev->r.retcode = transport->send_pdu(conn,
389223d6fefbSMike Christie (struct iscsi_hdr *)((char *)ev + sizeof(*ev)),
389323d6fefbSMike Christie (char *)ev + sizeof(*ev) + ev->u.send_pdu.hdr_size,
389423d6fefbSMike Christie ev->u.send_pdu.data_size);
389523d6fefbSMike Christie break;
389623d6fefbSMike Christie default:
389723d6fefbSMike Christie err = -ENOSYS;
389823d6fefbSMike Christie }
389923d6fefbSMike Christie
390023d6fefbSMike Christie mutex_unlock(&conn->ep_mutex);
390123d6fefbSMike Christie return err;
390223d6fefbSMike Christie }
39036fa7c554SLalit Chandivade
39046fa7c554SLalit Chandivade static int
iscsi_if_recv_msg(struct sk_buff * skb,struct nlmsghdr * nlh,uint32_t * group)390543514774SMichael Chan iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group)
39060896b752SAlex Aizman {
39070896b752SAlex Aizman int err = 0;
3908af170928SChris Leech u32 portid;
3909e07ebea0SHong zhi guo struct iscsi_uevent *ev = nlmsg_data(nlh);
39100896b752SAlex Aizman struct iscsi_transport *transport = NULL;
39110896b752SAlex Aizman struct iscsi_internal *priv;
39127b7232f3SMike Christie struct iscsi_cls_session *session;
3913d82ff9beSMike Christie struct iscsi_endpoint *ep = NULL;
3914971dfcb7SLin Ma u32 rlen;
39150896b752SAlex Aizman
3916688e8128SLee Duncan if (!netlink_capable(skb, CAP_SYS_ADMIN))
3917688e8128SLee Duncan return -EPERM;
3918688e8128SLee Duncan
391943514774SMichael Chan if (nlh->nlmsg_type == ISCSI_UEVENT_PATH_UPDATE)
392043514774SMichael Chan *group = ISCSI_NL_GRP_UIP;
392143514774SMichael Chan else
392243514774SMichael Chan *group = ISCSI_NL_GRP_ISCSID;
392343514774SMichael Chan
39240896b752SAlex Aizman priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
39250896b752SAlex Aizman if (!priv)
39260896b752SAlex Aizman return -EINVAL;
39270896b752SAlex Aizman transport = priv->iscsi_transport;
39280896b752SAlex Aizman
39297b7232f3SMike Christie if (!try_module_get(transport->owner))
39307b7232f3SMike Christie return -EINVAL;
39317b7232f3SMike Christie
3932af170928SChris Leech portid = NETLINK_CB(skb).portid;
3933af170928SChris Leech
3934971dfcb7SLin Ma /*
3935971dfcb7SLin Ma * Even though the remaining payload may not be regarded as nlattr,
3936971dfcb7SLin Ma * (like address or something else), calculate the remaining length
3937971dfcb7SLin Ma * here to ease following length checks.
3938971dfcb7SLin Ma */
3939971dfcb7SLin Ma rlen = nlmsg_attrlen(nlh, sizeof(*ev));
3940971dfcb7SLin Ma
39410896b752SAlex Aizman switch (nlh->nlmsg_type) {
39420896b752SAlex Aizman case ISCSI_UEVENT_CREATE_SESSION:
3943d82ff9beSMike Christie err = iscsi_if_create_session(priv, ep, ev,
3944af170928SChris Leech portid,
394540753caaSMike Christie ev->u.c_session.initial_cmdsn,
394640753caaSMike Christie ev->u.c_session.cmds_max,
394740753caaSMike Christie ev->u.c_session.queue_depth);
394840753caaSMike Christie break;
394940753caaSMike Christie case ISCSI_UEVENT_CREATE_BOUND_SESSION:
3950d82ff9beSMike Christie ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
3951c95fddc7SMike Christie if (!ep) {
3952c95fddc7SMike Christie err = -EINVAL;
3953c95fddc7SMike Christie break;
3954c95fddc7SMike Christie }
3955d82ff9beSMike Christie
3956d82ff9beSMike Christie err = iscsi_if_create_session(priv, ep, ev,
3957af170928SChris Leech portid,
395840753caaSMike Christie ev->u.c_bound_session.initial_cmdsn,
395940753caaSMike Christie ev->u.c_bound_session.cmds_max,
396040753caaSMike Christie ev->u.c_bound_session.queue_depth);
39619e5fe170SMike Christie iscsi_put_endpoint(ep);
39620896b752SAlex Aizman break;
39630896b752SAlex Aizman case ISCSI_UEVENT_DESTROY_SESSION:
3964b5c7a12dSMike Christie session = iscsi_session_lookup(ev->u.d_session.sid);
396554155ed4SNick Black if (!session)
396626974789SMike Christie err = -EINVAL;
396754155ed4SNick Black else if (iscsi_session_has_conns(ev->u.d_session.sid))
396854155ed4SNick Black err = -EBUSY;
396954155ed4SNick Black else
397054155ed4SNick Black transport->destroy_session(session);
397126974789SMike Christie break;
3972cc6b32eeSFrank Mayhar case ISCSI_UEVENT_DESTROY_SESSION_ASYNC:
3973cc6b32eeSFrank Mayhar session = iscsi_session_lookup(ev->u.d_session.sid);
3974cc6b32eeSFrank Mayhar if (!session)
3975cc6b32eeSFrank Mayhar err = -EINVAL;
3976cc6b32eeSFrank Mayhar else if (iscsi_session_has_conns(ev->u.d_session.sid))
3977cc6b32eeSFrank Mayhar err = -EBUSY;
3978cc6b32eeSFrank Mayhar else {
3979cc6b32eeSFrank Mayhar unsigned long flags;
3980cc6b32eeSFrank Mayhar
3981cc6b32eeSFrank Mayhar /* Prevent this session from being found again */
3982cc6b32eeSFrank Mayhar spin_lock_irqsave(&sesslock, flags);
398393bf02e5SMike Christie list_del_init(&session->sess_list);
3984cc6b32eeSFrank Mayhar spin_unlock_irqrestore(&sesslock, flags);
3985cc6b32eeSFrank Mayhar
3986b25b957dSMike Christie queue_work(system_unbound_wq, &session->destroy_work);
3987cc6b32eeSFrank Mayhar }
3988cc6b32eeSFrank Mayhar break;
398926974789SMike Christie case ISCSI_UEVENT_UNBIND_SESSION:
399026974789SMike Christie session = iscsi_session_lookup(ev->u.d_session.sid);
399126974789SMike Christie if (session)
39925842ea36SMike Christie queue_work(session->workq, &session->unbind_work);
399326974789SMike Christie else
39947b7232f3SMike Christie err = -EINVAL;
39950896b752SAlex Aizman break;
39960896b752SAlex Aizman case ISCSI_UEVENT_SET_PARAM:
3997971dfcb7SLin Ma err = iscsi_if_set_param(transport, ev, rlen);
39980896b752SAlex Aizman break;
399923d6fefbSMike Christie case ISCSI_UEVENT_CREATE_CONN:
400023d6fefbSMike Christie case ISCSI_UEVENT_DESTROY_CONN:
40010896b752SAlex Aizman case ISCSI_UEVENT_STOP_CONN:
400223d6fefbSMike Christie case ISCSI_UEVENT_START_CONN:
400323d6fefbSMike Christie case ISCSI_UEVENT_BIND_CONN:
40040896b752SAlex Aizman case ISCSI_UEVENT_SEND_PDU:
4005971dfcb7SLin Ma err = iscsi_if_transport_conn(transport, nlh, rlen);
40060896b752SAlex Aizman break;
40070896b752SAlex Aizman case ISCSI_UEVENT_GET_STATS:
40085b940adfSMike Christie err = iscsi_if_get_stats(transport, nlh);
40090896b752SAlex Aizman break;
4010264faaaaSOr Gerlitz case ISCSI_UEVENT_TRANSPORT_EP_CONNECT:
4011264faaaaSOr Gerlitz case ISCSI_UEVENT_TRANSPORT_EP_POLL:
4012264faaaaSOr Gerlitz case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
401310eb0f01SMike Christie case ISCSI_UEVENT_TRANSPORT_EP_CONNECT_THROUGH_HOST:
4014971dfcb7SLin Ma err = iscsi_if_transport_ep(transport, ev, nlh->nlmsg_type, rlen);
4015264faaaaSOr Gerlitz break;
401601cb225dSMike Christie case ISCSI_UEVENT_TGT_DSCVR:
4017971dfcb7SLin Ma err = iscsi_tgt_dscvr(transport, ev, rlen);
401801cb225dSMike Christie break;
40191d9bf13aSMike Christie case ISCSI_UEVENT_SET_HOST_PARAM:
4020971dfcb7SLin Ma err = iscsi_set_host_param(transport, ev, rlen);
40211d9bf13aSMike Christie break;
402243514774SMichael Chan case ISCSI_UEVENT_PATH_UPDATE:
4023971dfcb7SLin Ma err = iscsi_set_path(transport, ev, rlen);
402443514774SMichael Chan break;
402556c155b5SMike Christie case ISCSI_UEVENT_SET_IFACE_PARAMS:
4026971dfcb7SLin Ma err = iscsi_set_iface_params(transport, ev, rlen);
402756c155b5SMike Christie break;
4028ac20c7bfSVikas Chaudhary case ISCSI_UEVENT_PING:
4029971dfcb7SLin Ma err = iscsi_send_ping(transport, ev, rlen);
4030ac20c7bfSVikas Chaudhary break;
40316260a5d2SNilesh Javali case ISCSI_UEVENT_GET_CHAP:
40326260a5d2SNilesh Javali err = iscsi_get_chap(transport, nlh);
40336260a5d2SNilesh Javali break;
40346260a5d2SNilesh Javali case ISCSI_UEVENT_DELETE_CHAP:
40356260a5d2SNilesh Javali err = iscsi_delete_chap(transport, ev);
40366260a5d2SNilesh Javali break;
4037c6a4bb2eSAdheer Chandravanshi case ISCSI_UEVENT_SET_FLASHNODE_PARAMS:
4038971dfcb7SLin Ma err = iscsi_set_flashnode_param(transport, ev, rlen);
4039c6a4bb2eSAdheer Chandravanshi break;
4040c6a4bb2eSAdheer Chandravanshi case ISCSI_UEVENT_NEW_FLASHNODE:
4041971dfcb7SLin Ma err = iscsi_new_flashnode(transport, ev, rlen);
4042c6a4bb2eSAdheer Chandravanshi break;
4043c6a4bb2eSAdheer Chandravanshi case ISCSI_UEVENT_DEL_FLASHNODE:
4044c6a4bb2eSAdheer Chandravanshi err = iscsi_del_flashnode(transport, ev);
4045c6a4bb2eSAdheer Chandravanshi break;
4046c6a4bb2eSAdheer Chandravanshi case ISCSI_UEVENT_LOGIN_FLASHNODE:
4047c6a4bb2eSAdheer Chandravanshi err = iscsi_login_flashnode(transport, ev);
4048c6a4bb2eSAdheer Chandravanshi break;
4049c6a4bb2eSAdheer Chandravanshi case ISCSI_UEVENT_LOGOUT_FLASHNODE:
4050c6a4bb2eSAdheer Chandravanshi err = iscsi_logout_flashnode(transport, ev);
4051c6a4bb2eSAdheer Chandravanshi break;
4052c6a4bb2eSAdheer Chandravanshi case ISCSI_UEVENT_LOGOUT_FLASHNODE_SID:
4053c6a4bb2eSAdheer Chandravanshi err = iscsi_logout_flashnode_sid(transport, ev);
4054c6a4bb2eSAdheer Chandravanshi break;
40553af142feSAdheer Chandravanshi case ISCSI_UEVENT_SET_CHAP:
4056971dfcb7SLin Ma err = iscsi_set_chap(transport, ev, rlen);
40573af142feSAdheer Chandravanshi break;
40586fa7c554SLalit Chandivade case ISCSI_UEVENT_GET_HOST_STATS:
40596fa7c554SLalit Chandivade err = iscsi_get_host_stats(transport, nlh);
40606fa7c554SLalit Chandivade break;
40610896b752SAlex Aizman default:
40621d9bf13aSMike Christie err = -ENOSYS;
40630896b752SAlex Aizman break;
40640896b752SAlex Aizman }
40650896b752SAlex Aizman
40667b7232f3SMike Christie module_put(transport->owner);
40670896b752SAlex Aizman return err;
40680896b752SAlex Aizman }
40690896b752SAlex Aizman
4070b5c7a12dSMike Christie /*
4071cd40b7d3SDenis V. Lunev * Get message from skb. Each message is processed by iscsi_if_recv_msg.
4072cd40b7d3SDenis V. Lunev * Malformed skbs with wrong lengths or invalid creds are not processed.
4073b5c7a12dSMike Christie */
40740896b752SAlex Aizman static void
iscsi_if_rx(struct sk_buff * skb)4075cd40b7d3SDenis V. Lunev iscsi_if_rx(struct sk_buff *skb)
40760896b752SAlex Aizman {
4077af170928SChris Leech u32 portid = NETLINK_CB(skb).portid;
4078af170928SChris Leech
40790b950672SArjan van de Ven mutex_lock(&rx_queue_mutex);
4080e07ebea0SHong zhi guo while (skb->len >= NLMSG_HDRLEN) {
40810896b752SAlex Aizman int err;
40820896b752SAlex Aizman uint32_t rlen;
40830896b752SAlex Aizman struct nlmsghdr *nlh;
40840896b752SAlex Aizman struct iscsi_uevent *ev;
408543514774SMichael Chan uint32_t group;
4086bba340c7SBo Wu int retries = ISCSI_SEND_MAX_ALLOWED;
40870896b752SAlex Aizman
4088b529ccf2SArnaldo Carvalho de Melo nlh = nlmsg_hdr(skb);
4089c88f0e6bSXin Long if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) ||
40900896b752SAlex Aizman skb->len < nlh->nlmsg_len) {
40910896b752SAlex Aizman break;
40920896b752SAlex Aizman }
4093ee7f8e40SMike Christie
4094e07ebea0SHong zhi guo ev = nlmsg_data(nlh);
40950896b752SAlex Aizman rlen = NLMSG_ALIGN(nlh->nlmsg_len);
40960896b752SAlex Aizman if (rlen > skb->len)
40970896b752SAlex Aizman rlen = skb->len;
4098ee7f8e40SMike Christie
409943514774SMichael Chan err = iscsi_if_recv_msg(skb, nlh, &group);
41000896b752SAlex Aizman if (err) {
41010896b752SAlex Aizman ev->type = ISCSI_KEVENT_IF_ERROR;
41020896b752SAlex Aizman ev->iferror = err;
41030896b752SAlex Aizman }
41040896b752SAlex Aizman do {
41050896b752SAlex Aizman /*
4106*44c485f0SXiang Zhang * special case for GET_STATS, GET_CHAP and GET_HOST_STATS:
41070896b752SAlex Aizman * on success - sending reply and stats from
41080896b752SAlex Aizman * inside of if_recv_msg(),
41090896b752SAlex Aizman * on error - fall through.
41100896b752SAlex Aizman */
41110896b752SAlex Aizman if (ev->type == ISCSI_UEVENT_GET_STATS && !err)
41120896b752SAlex Aizman break;
41136260a5d2SNilesh Javali if (ev->type == ISCSI_UEVENT_GET_CHAP && !err)
41146260a5d2SNilesh Javali break;
4115*44c485f0SXiang Zhang if (ev->type == ISCSI_UEVENT_GET_HOST_STATS && !err)
4116*44c485f0SXiang Zhang break;
4117af170928SChris Leech err = iscsi_if_send_reply(portid, nlh->nlmsg_type,
4118af170928SChris Leech ev, sizeof(*ev));
4119bba340c7SBo Wu if (err == -EAGAIN && --retries < 0) {
4120bba340c7SBo Wu printk(KERN_WARNING "Send reply failed, error %d\n", err);
4121bba340c7SBo Wu break;
4122bba340c7SBo Wu }
412346a7c17dSSasha Levin } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH);
41240896b752SAlex Aizman skb_pull(skb, rlen);
41250896b752SAlex Aizman }
41260b950672SArjan van de Ven mutex_unlock(&rx_queue_mutex);
41270896b752SAlex Aizman }
41280896b752SAlex Aizman
4129fd7255f5SMike Christie #define ISCSI_CLASS_ATTR(_prefix,_name,_mode,_show,_store) \
4130ee959b00STony Jones struct device_attribute dev_attr_##_prefix##_##_name = \
4131fd7255f5SMike Christie __ATTR(_name,_mode,_show,_store)
4132fd7255f5SMike Christie
41330896b752SAlex Aizman /*
41340896b752SAlex Aizman * iSCSI connection attrs
41350896b752SAlex Aizman */
4136a54a52caSMike Christie #define iscsi_conn_attr_show(param) \
41370896b752SAlex Aizman static ssize_t \
4138ee959b00STony Jones show_conn_param_##param(struct device *dev, \
4139ee959b00STony Jones struct device_attribute *attr, char *buf) \
4140fd7255f5SMike Christie { \
4141ee959b00STony Jones struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); \
4142fd7255f5SMike Christie struct iscsi_transport *t = conn->transport; \
4143a54a52caSMike Christie return t->get_conn_param(conn, param, buf); \
4144fd7255f5SMike Christie }
4145fd7255f5SMike Christie
4146a54a52caSMike Christie #define iscsi_conn_attr(field, param) \
4147a54a52caSMike Christie iscsi_conn_attr_show(param) \
4148a54a52caSMike Christie static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, show_conn_param_##param, \
4149fd7255f5SMike Christie NULL);
4150fd7255f5SMike Christie
4151a54a52caSMike Christie iscsi_conn_attr(max_recv_dlength, ISCSI_PARAM_MAX_RECV_DLENGTH);
4152a54a52caSMike Christie iscsi_conn_attr(max_xmit_dlength, ISCSI_PARAM_MAX_XMIT_DLENGTH);
4153a54a52caSMike Christie iscsi_conn_attr(header_digest, ISCSI_PARAM_HDRDGST_EN);
4154a54a52caSMike Christie iscsi_conn_attr(data_digest, ISCSI_PARAM_DATADGST_EN);
4155a54a52caSMike Christie iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
4156a54a52caSMike Christie iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
4157a54a52caSMike Christie iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
4158a54a52caSMike Christie iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
4159a54a52caSMike Christie iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
4160f6d5180cSMike Christie iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
4161f6d5180cSMike Christie iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
4162ae542edbSAdheer Chandravanshi iscsi_conn_attr(local_port, ISCSI_PARAM_LOCAL_PORT);
4163ae542edbSAdheer Chandravanshi iscsi_conn_attr(statsn, ISCSI_PARAM_STATSN);
4164ae542edbSAdheer Chandravanshi iscsi_conn_attr(keepalive_tmo, ISCSI_PARAM_KEEPALIVE_TMO);
4165ae542edbSAdheer Chandravanshi iscsi_conn_attr(max_segment_size, ISCSI_PARAM_MAX_SEGMENT_SIZE);
4166ae542edbSAdheer Chandravanshi iscsi_conn_attr(tcp_timestamp_stat, ISCSI_PARAM_TCP_TIMESTAMP_STAT);
4167ae542edbSAdheer Chandravanshi iscsi_conn_attr(tcp_wsf_disable, ISCSI_PARAM_TCP_WSF_DISABLE);
4168ae542edbSAdheer Chandravanshi iscsi_conn_attr(tcp_nagle_disable, ISCSI_PARAM_TCP_NAGLE_DISABLE);
4169ae542edbSAdheer Chandravanshi iscsi_conn_attr(tcp_timer_scale, ISCSI_PARAM_TCP_TIMER_SCALE);
4170ae542edbSAdheer Chandravanshi iscsi_conn_attr(tcp_timestamp_enable, ISCSI_PARAM_TCP_TIMESTAMP_EN);
4171ae542edbSAdheer Chandravanshi iscsi_conn_attr(fragment_disable, ISCSI_PARAM_IP_FRAGMENT_DISABLE);
4172ae542edbSAdheer Chandravanshi iscsi_conn_attr(ipv4_tos, ISCSI_PARAM_IPV4_TOS);
4173ae542edbSAdheer Chandravanshi iscsi_conn_attr(ipv6_traffic_class, ISCSI_PARAM_IPV6_TC);
4174ae542edbSAdheer Chandravanshi iscsi_conn_attr(ipv6_flow_label, ISCSI_PARAM_IPV6_FLOW_LABEL);
4175ae542edbSAdheer Chandravanshi iscsi_conn_attr(is_fw_assigned_ipv6, ISCSI_PARAM_IS_FW_ASSIGNED_IPV6);
4176ae542edbSAdheer Chandravanshi iscsi_conn_attr(tcp_xmit_wsf, ISCSI_PARAM_TCP_XMIT_WSF);
4177ae542edbSAdheer Chandravanshi iscsi_conn_attr(tcp_recv_wsf, ISCSI_PARAM_TCP_RECV_WSF);
41785af62f24SAdheer Chandravanshi iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR);
4179ae542edbSAdheer Chandravanshi
418082b8cf40SGabriel Krisman Bertazi static const char *const connection_state_names[] = {
418182b8cf40SGabriel Krisman Bertazi [ISCSI_CONN_UP] = "up",
418282b8cf40SGabriel Krisman Bertazi [ISCSI_CONN_DOWN] = "down",
41839e67600eSGulam Mohamed [ISCSI_CONN_FAILED] = "failed",
41849e67600eSGulam Mohamed [ISCSI_CONN_BOUND] = "bound"
418582b8cf40SGabriel Krisman Bertazi };
418682b8cf40SGabriel Krisman Bertazi
show_conn_state(struct device * dev,struct device_attribute * attr,char * buf)418782b8cf40SGabriel Krisman Bertazi static ssize_t show_conn_state(struct device *dev,
418882b8cf40SGabriel Krisman Bertazi struct device_attribute *attr, char *buf)
418982b8cf40SGabriel Krisman Bertazi {
419082b8cf40SGabriel Krisman Bertazi struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);
419182b8cf40SGabriel Krisman Bertazi const char *state = "unknown";
419203690d81SMike Christie int conn_state = READ_ONCE(conn->state);
419382b8cf40SGabriel Krisman Bertazi
419403690d81SMike Christie if (conn_state >= 0 &&
419503690d81SMike Christie conn_state < ARRAY_SIZE(connection_state_names))
419603690d81SMike Christie state = connection_state_names[conn_state];
419782b8cf40SGabriel Krisman Bertazi
4198ec98ea70SChris Leech return sysfs_emit(buf, "%s\n", state);
419982b8cf40SGabriel Krisman Bertazi }
420082b8cf40SGabriel Krisman Bertazi static ISCSI_CLASS_ATTR(conn, state, S_IRUGO, show_conn_state,
420182b8cf40SGabriel Krisman Bertazi NULL);
42020896b752SAlex Aizman
4203289324b0SMike Christie #define iscsi_conn_ep_attr_show(param) \
4204289324b0SMike Christie static ssize_t show_conn_ep_param_##param(struct device *dev, \
4205289324b0SMike Christie struct device_attribute *attr,\
4206289324b0SMike Christie char *buf) \
4207289324b0SMike Christie { \
4208289324b0SMike Christie struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent); \
4209289324b0SMike Christie struct iscsi_transport *t = conn->transport; \
4210289324b0SMike Christie struct iscsi_endpoint *ep; \
4211289324b0SMike Christie ssize_t rc; \
4212289324b0SMike Christie \
4213289324b0SMike Christie /* \
4214289324b0SMike Christie * Need to make sure ep_disconnect does not free the LLD's \
4215289324b0SMike Christie * interconnect resources while we are trying to read them. \
4216289324b0SMike Christie */ \
4217289324b0SMike Christie mutex_lock(&conn->ep_mutex); \
4218289324b0SMike Christie ep = conn->ep; \
4219289324b0SMike Christie if (!ep && t->ep_connect) { \
4220289324b0SMike Christie mutex_unlock(&conn->ep_mutex); \
4221289324b0SMike Christie return -ENOTCONN; \
4222289324b0SMike Christie } \
4223289324b0SMike Christie \
4224289324b0SMike Christie if (ep) \
4225289324b0SMike Christie rc = t->get_ep_param(ep, param, buf); \
4226289324b0SMike Christie else \
4227289324b0SMike Christie rc = t->get_conn_param(conn, param, buf); \
4228289324b0SMike Christie mutex_unlock(&conn->ep_mutex); \
4229289324b0SMike Christie return rc; \
4230289324b0SMike Christie }
4231289324b0SMike Christie
4232289324b0SMike Christie #define iscsi_conn_ep_attr(field, param) \
4233289324b0SMike Christie iscsi_conn_ep_attr_show(param) \
4234289324b0SMike Christie static ISCSI_CLASS_ATTR(conn, field, S_IRUGO, \
4235289324b0SMike Christie show_conn_ep_param_##param, NULL);
4236289324b0SMike Christie
4237289324b0SMike Christie iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
4238289324b0SMike Christie iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
4239289324b0SMike Christie
42403128c6c7SMike Christie static struct attribute *iscsi_conn_attrs[] = {
42413128c6c7SMike Christie &dev_attr_conn_max_recv_dlength.attr,
42423128c6c7SMike Christie &dev_attr_conn_max_xmit_dlength.attr,
42433128c6c7SMike Christie &dev_attr_conn_header_digest.attr,
42443128c6c7SMike Christie &dev_attr_conn_data_digest.attr,
42453128c6c7SMike Christie &dev_attr_conn_ifmarker.attr,
42463128c6c7SMike Christie &dev_attr_conn_ofmarker.attr,
42473128c6c7SMike Christie &dev_attr_conn_address.attr,
42483128c6c7SMike Christie &dev_attr_conn_port.attr,
42493128c6c7SMike Christie &dev_attr_conn_exp_statsn.attr,
42503128c6c7SMike Christie &dev_attr_conn_persistent_address.attr,
42513128c6c7SMike Christie &dev_attr_conn_persistent_port.attr,
42523128c6c7SMike Christie &dev_attr_conn_ping_tmo.attr,
42533128c6c7SMike Christie &dev_attr_conn_recv_tmo.attr,
4254ae542edbSAdheer Chandravanshi &dev_attr_conn_local_port.attr,
4255ae542edbSAdheer Chandravanshi &dev_attr_conn_statsn.attr,
4256ae542edbSAdheer Chandravanshi &dev_attr_conn_keepalive_tmo.attr,
4257ae542edbSAdheer Chandravanshi &dev_attr_conn_max_segment_size.attr,
4258ae542edbSAdheer Chandravanshi &dev_attr_conn_tcp_timestamp_stat.attr,
4259ae542edbSAdheer Chandravanshi &dev_attr_conn_tcp_wsf_disable.attr,
4260ae542edbSAdheer Chandravanshi &dev_attr_conn_tcp_nagle_disable.attr,
4261ae542edbSAdheer Chandravanshi &dev_attr_conn_tcp_timer_scale.attr,
4262ae542edbSAdheer Chandravanshi &dev_attr_conn_tcp_timestamp_enable.attr,
4263ae542edbSAdheer Chandravanshi &dev_attr_conn_fragment_disable.attr,
4264ae542edbSAdheer Chandravanshi &dev_attr_conn_ipv4_tos.attr,
4265ae542edbSAdheer Chandravanshi &dev_attr_conn_ipv6_traffic_class.attr,
4266ae542edbSAdheer Chandravanshi &dev_attr_conn_ipv6_flow_label.attr,
4267ae542edbSAdheer Chandravanshi &dev_attr_conn_is_fw_assigned_ipv6.attr,
4268ae542edbSAdheer Chandravanshi &dev_attr_conn_tcp_xmit_wsf.attr,
4269ae542edbSAdheer Chandravanshi &dev_attr_conn_tcp_recv_wsf.attr,
42705af62f24SAdheer Chandravanshi &dev_attr_conn_local_ipaddr.attr,
427182b8cf40SGabriel Krisman Bertazi &dev_attr_conn_state.attr,
42723128c6c7SMike Christie NULL,
42733128c6c7SMike Christie };
42743128c6c7SMike Christie
iscsi_conn_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)4275587a1f16SAl Viro static umode_t iscsi_conn_attr_is_visible(struct kobject *kobj,
42763128c6c7SMike Christie struct attribute *attr, int i)
42773128c6c7SMike Christie {
42783128c6c7SMike Christie struct device *cdev = container_of(kobj, struct device, kobj);
42793128c6c7SMike Christie struct iscsi_cls_conn *conn = transport_class_to_conn(cdev);
42803128c6c7SMike Christie struct iscsi_transport *t = conn->transport;
42813128c6c7SMike Christie int param;
42823128c6c7SMike Christie
42833128c6c7SMike Christie if (attr == &dev_attr_conn_max_recv_dlength.attr)
42843128c6c7SMike Christie param = ISCSI_PARAM_MAX_RECV_DLENGTH;
42853128c6c7SMike Christie else if (attr == &dev_attr_conn_max_xmit_dlength.attr)
42863128c6c7SMike Christie param = ISCSI_PARAM_MAX_XMIT_DLENGTH;
42873128c6c7SMike Christie else if (attr == &dev_attr_conn_header_digest.attr)
42883128c6c7SMike Christie param = ISCSI_PARAM_HDRDGST_EN;
42893128c6c7SMike Christie else if (attr == &dev_attr_conn_data_digest.attr)
42903128c6c7SMike Christie param = ISCSI_PARAM_DATADGST_EN;
42913128c6c7SMike Christie else if (attr == &dev_attr_conn_ifmarker.attr)
42923128c6c7SMike Christie param = ISCSI_PARAM_IFMARKER_EN;
42933128c6c7SMike Christie else if (attr == &dev_attr_conn_ofmarker.attr)
42943128c6c7SMike Christie param = ISCSI_PARAM_OFMARKER_EN;
42953128c6c7SMike Christie else if (attr == &dev_attr_conn_address.attr)
42963128c6c7SMike Christie param = ISCSI_PARAM_CONN_ADDRESS;
42973128c6c7SMike Christie else if (attr == &dev_attr_conn_port.attr)
42983128c6c7SMike Christie param = ISCSI_PARAM_CONN_PORT;
42993128c6c7SMike Christie else if (attr == &dev_attr_conn_exp_statsn.attr)
43003128c6c7SMike Christie param = ISCSI_PARAM_EXP_STATSN;
43013128c6c7SMike Christie else if (attr == &dev_attr_conn_persistent_address.attr)
43023128c6c7SMike Christie param = ISCSI_PARAM_PERSISTENT_ADDRESS;
43033128c6c7SMike Christie else if (attr == &dev_attr_conn_persistent_port.attr)
43043128c6c7SMike Christie param = ISCSI_PARAM_PERSISTENT_PORT;
43053128c6c7SMike Christie else if (attr == &dev_attr_conn_ping_tmo.attr)
43063128c6c7SMike Christie param = ISCSI_PARAM_PING_TMO;
43073128c6c7SMike Christie else if (attr == &dev_attr_conn_recv_tmo.attr)
43083128c6c7SMike Christie param = ISCSI_PARAM_RECV_TMO;
4309ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_local_port.attr)
4310ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_LOCAL_PORT;
4311ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_statsn.attr)
4312ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_STATSN;
4313ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_keepalive_tmo.attr)
4314ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_KEEPALIVE_TMO;
4315ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_max_segment_size.attr)
4316ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_MAX_SEGMENT_SIZE;
4317ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_tcp_timestamp_stat.attr)
4318ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_TCP_TIMESTAMP_STAT;
4319ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_tcp_wsf_disable.attr)
4320ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_TCP_WSF_DISABLE;
4321ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_tcp_nagle_disable.attr)
4322ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_TCP_NAGLE_DISABLE;
4323ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_tcp_timer_scale.attr)
4324ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_TCP_TIMER_SCALE;
4325ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_tcp_timestamp_enable.attr)
4326ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_TCP_TIMESTAMP_EN;
4327ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_fragment_disable.attr)
4328ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_IP_FRAGMENT_DISABLE;
4329ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_ipv4_tos.attr)
4330ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_IPV4_TOS;
4331ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_ipv6_traffic_class.attr)
4332ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_IPV6_TC;
4333ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_ipv6_flow_label.attr)
4334ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_IPV6_FLOW_LABEL;
4335ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_is_fw_assigned_ipv6.attr)
4336ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_IS_FW_ASSIGNED_IPV6;
4337ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_tcp_xmit_wsf.attr)
4338ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_TCP_XMIT_WSF;
4339ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_conn_tcp_recv_wsf.attr)
4340ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_TCP_RECV_WSF;
43415af62f24SAdheer Chandravanshi else if (attr == &dev_attr_conn_local_ipaddr.attr)
43425af62f24SAdheer Chandravanshi param = ISCSI_PARAM_LOCAL_IPADDR;
434382b8cf40SGabriel Krisman Bertazi else if (attr == &dev_attr_conn_state.attr)
434482b8cf40SGabriel Krisman Bertazi return S_IRUGO;
43453128c6c7SMike Christie else {
43463128c6c7SMike Christie WARN_ONCE(1, "Invalid conn attr");
43473128c6c7SMike Christie return 0;
43483128c6c7SMike Christie }
43493128c6c7SMike Christie
43503128c6c7SMike Christie return t->attr_is_visible(ISCSI_PARAM, param);
43513128c6c7SMike Christie }
43523128c6c7SMike Christie
43533128c6c7SMike Christie static struct attribute_group iscsi_conn_group = {
43543128c6c7SMike Christie .attrs = iscsi_conn_attrs,
43553128c6c7SMike Christie .is_visible = iscsi_conn_attr_is_visible,
43563128c6c7SMike Christie };
43573128c6c7SMike Christie
43580896b752SAlex Aizman /*
43590896b752SAlex Aizman * iSCSI session attrs
43600896b752SAlex Aizman */
4361b2c64167SMike Christie #define iscsi_session_attr_show(param, perm) \
43620896b752SAlex Aizman static ssize_t \
4363ee959b00STony Jones show_session_param_##param(struct device *dev, \
4364ee959b00STony Jones struct device_attribute *attr, char *buf) \
4365fd7255f5SMike Christie { \
4366ee959b00STony Jones struct iscsi_cls_session *session = \
4367ee959b00STony Jones iscsi_dev_to_session(dev->parent); \
4368fd7255f5SMike Christie struct iscsi_transport *t = session->transport; \
4369b2c64167SMike Christie \
4370b2c64167SMike Christie if (perm && !capable(CAP_SYS_ADMIN)) \
4371b2c64167SMike Christie return -EACCES; \
4372a54a52caSMike Christie return t->get_session_param(session, param, buf); \
43730896b752SAlex Aizman }
43740896b752SAlex Aizman
4375b2c64167SMike Christie #define iscsi_session_attr(field, param, perm) \
4376b2c64167SMike Christie iscsi_session_attr_show(param, perm) \
4377a54a52caSMike Christie static ISCSI_CLASS_ATTR(sess, field, S_IRUGO, show_session_param_##param, \
4378fd7255f5SMike Christie NULL);
4379b2c64167SMike Christie iscsi_session_attr(targetname, ISCSI_PARAM_TARGET_NAME, 0);
4380b2c64167SMike Christie iscsi_session_attr(initial_r2t, ISCSI_PARAM_INITIAL_R2T_EN, 0);
4381b2c64167SMike Christie iscsi_session_attr(max_outstanding_r2t, ISCSI_PARAM_MAX_R2T, 0);
4382b2c64167SMike Christie iscsi_session_attr(immediate_data, ISCSI_PARAM_IMM_DATA_EN, 0);
4383b2c64167SMike Christie iscsi_session_attr(first_burst_len, ISCSI_PARAM_FIRST_BURST, 0);
4384b2c64167SMike Christie iscsi_session_attr(max_burst_len, ISCSI_PARAM_MAX_BURST, 0);
4385b2c64167SMike Christie iscsi_session_attr(data_pdu_in_order, ISCSI_PARAM_PDU_INORDER_EN, 0);
4386b2c64167SMike Christie iscsi_session_attr(data_seq_in_order, ISCSI_PARAM_DATASEQ_INORDER_EN, 0);
4387b2c64167SMike Christie iscsi_session_attr(erl, ISCSI_PARAM_ERL, 0);
4388b2c64167SMike Christie iscsi_session_attr(tpgt, ISCSI_PARAM_TPGT, 0);
4389b2c64167SMike Christie iscsi_session_attr(username, ISCSI_PARAM_USERNAME, 1);
4390b2c64167SMike Christie iscsi_session_attr(username_in, ISCSI_PARAM_USERNAME_IN, 1);
4391b2c64167SMike Christie iscsi_session_attr(password, ISCSI_PARAM_PASSWORD, 1);
4392b2c64167SMike Christie iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);
439330534952SMike Christie iscsi_session_attr(chap_out_idx, ISCSI_PARAM_CHAP_OUT_IDX, 1);
439430534952SMike Christie iscsi_session_attr(chap_in_idx, ISCSI_PARAM_CHAP_IN_IDX, 1);
43954cd49ea1SMike Christie iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);
43964cd49ea1SMike Christie iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);
43974cd49ea1SMike Christie iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0);
43983fe5ae8bSMike Christie iscsi_session_attr(tgt_reset_tmo, ISCSI_PARAM_TGT_RESET_TMO, 0);
439988dfd340SMike Christie iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0);
44003b2bef1fSVikas Chaudhary iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0);
44013b2bef1fSVikas Chaudhary iscsi_session_attr(targetalias, ISCSI_PARAM_TARGET_ALIAS, 0);
44023b9373e9SEddie Wai iscsi_session_attr(boot_root, ISCSI_PARAM_BOOT_ROOT, 0);
44033b9373e9SEddie Wai iscsi_session_attr(boot_nic, ISCSI_PARAM_BOOT_NIC, 0);
44043b9373e9SEddie Wai iscsi_session_attr(boot_target, ISCSI_PARAM_BOOT_TARGET, 0);
4405ae542edbSAdheer Chandravanshi iscsi_session_attr(auto_snd_tgt_disable, ISCSI_PARAM_AUTO_SND_TGT_DISABLE, 0);
4406ae542edbSAdheer Chandravanshi iscsi_session_attr(discovery_session, ISCSI_PARAM_DISCOVERY_SESS, 0);
4407ae542edbSAdheer Chandravanshi iscsi_session_attr(portal_type, ISCSI_PARAM_PORTAL_TYPE, 0);
4408ae542edbSAdheer Chandravanshi iscsi_session_attr(chap_auth, ISCSI_PARAM_CHAP_AUTH_EN, 0);
4409ae542edbSAdheer Chandravanshi iscsi_session_attr(discovery_logout, ISCSI_PARAM_DISCOVERY_LOGOUT_EN, 0);
4410ae542edbSAdheer Chandravanshi iscsi_session_attr(bidi_chap, ISCSI_PARAM_BIDI_CHAP_EN, 0);
4411ae542edbSAdheer Chandravanshi iscsi_session_attr(discovery_auth_optional,
4412ae542edbSAdheer Chandravanshi ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL, 0);
4413ae542edbSAdheer Chandravanshi iscsi_session_attr(def_time2wait, ISCSI_PARAM_DEF_TIME2WAIT, 0);
4414ae542edbSAdheer Chandravanshi iscsi_session_attr(def_time2retain, ISCSI_PARAM_DEF_TIME2RETAIN, 0);
4415ae542edbSAdheer Chandravanshi iscsi_session_attr(isid, ISCSI_PARAM_ISID, 0);
4416ae542edbSAdheer Chandravanshi iscsi_session_attr(tsid, ISCSI_PARAM_TSID, 0);
4417ae542edbSAdheer Chandravanshi iscsi_session_attr(def_taskmgmt_tmo, ISCSI_PARAM_DEF_TASKMGMT_TMO, 0);
4418ae542edbSAdheer Chandravanshi iscsi_session_attr(discovery_parent_idx, ISCSI_PARAM_DISCOVERY_PARENT_IDX, 0);
4419ae542edbSAdheer Chandravanshi iscsi_session_attr(discovery_parent_type, ISCSI_PARAM_DISCOVERY_PARENT_TYPE, 0);
4420fd7255f5SMike Christie
44216eabafbeSMike Christie static ssize_t
show_priv_session_target_state(struct device * dev,struct device_attribute * attr,char * buf)4422a3be19b9SWenchao Hao show_priv_session_target_state(struct device *dev, struct device_attribute *attr,
4423a3be19b9SWenchao Hao char *buf)
4424a3be19b9SWenchao Hao {
4425a3be19b9SWenchao Hao struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
4426a3be19b9SWenchao Hao
4427a3be19b9SWenchao Hao return sysfs_emit(buf, "%s\n",
4428a3be19b9SWenchao Hao iscsi_session_target_state_name[session->target_state]);
4429a3be19b9SWenchao Hao }
4430a3be19b9SWenchao Hao
4431a3be19b9SWenchao Hao static ISCSI_CLASS_ATTR(priv_sess, target_state, S_IRUGO,
4432a3be19b9SWenchao Hao show_priv_session_target_state, NULL);
4433a3be19b9SWenchao Hao
4434a3be19b9SWenchao Hao static ssize_t
show_priv_session_state(struct device * dev,struct device_attribute * attr,char * buf)4435ee959b00STony Jones show_priv_session_state(struct device *dev, struct device_attribute *attr,
4436ee959b00STony Jones char *buf)
44376eabafbeSMike Christie {
4438ee959b00STony Jones struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
4439ec98ea70SChris Leech return sysfs_emit(buf, "%s\n", iscsi_session_state_name(session->state));
44406eabafbeSMike Christie }
44416eabafbeSMike Christie static ISCSI_CLASS_ATTR(priv_sess, state, S_IRUGO, show_priv_session_state,
44426eabafbeSMike Christie NULL);
44430c70d84bSMike Christie static ssize_t
show_priv_session_creator(struct device * dev,struct device_attribute * attr,char * buf)44440c70d84bSMike Christie show_priv_session_creator(struct device *dev, struct device_attribute *attr,
44450c70d84bSMike Christie char *buf)
44460c70d84bSMike Christie {
44470c70d84bSMike Christie struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
4448ec98ea70SChris Leech return sysfs_emit(buf, "%d\n", session->creator);
44490c70d84bSMike Christie }
44500c70d84bSMike Christie static ISCSI_CLASS_ATTR(priv_sess, creator, S_IRUGO, show_priv_session_creator,
44510c70d84bSMike Christie NULL);
4452930a9f04SManish Rangankar static ssize_t
show_priv_session_target_id(struct device * dev,struct device_attribute * attr,char * buf)4453930a9f04SManish Rangankar show_priv_session_target_id(struct device *dev, struct device_attribute *attr,
4454930a9f04SManish Rangankar char *buf)
4455930a9f04SManish Rangankar {
4456930a9f04SManish Rangankar struct iscsi_cls_session *session = iscsi_dev_to_session(dev->parent);
4457ec98ea70SChris Leech return sysfs_emit(buf, "%d\n", session->target_id);
4458930a9f04SManish Rangankar }
4459930a9f04SManish Rangankar static ISCSI_CLASS_ATTR(priv_sess, target_id, S_IRUGO,
4460930a9f04SManish Rangankar show_priv_session_target_id, NULL);
44616eabafbeSMike Christie
4462fd7255f5SMike Christie #define iscsi_priv_session_attr_show(field, format) \
4463fd7255f5SMike Christie static ssize_t \
4464ee959b00STony Jones show_priv_session_##field(struct device *dev, \
4465ee959b00STony Jones struct device_attribute *attr, char *buf) \
4466fd7255f5SMike Christie { \
4467ee959b00STony Jones struct iscsi_cls_session *session = \
4468ee959b00STony Jones iscsi_dev_to_session(dev->parent); \
4469fe4f0bdeSVikas Chaudhary if (session->field == -1) \
4470ec98ea70SChris Leech return sysfs_emit(buf, "off\n"); \
4471ec98ea70SChris Leech return sysfs_emit(buf, format"\n", session->field); \
44720896b752SAlex Aizman }
44730896b752SAlex Aizman
4474fe4f0bdeSVikas Chaudhary #define iscsi_priv_session_attr_store(field) \
4475fe4f0bdeSVikas Chaudhary static ssize_t \
4476fe4f0bdeSVikas Chaudhary store_priv_session_##field(struct device *dev, \
4477fe4f0bdeSVikas Chaudhary struct device_attribute *attr, \
4478fe4f0bdeSVikas Chaudhary const char *buf, size_t count) \
4479fe4f0bdeSVikas Chaudhary { \
4480fe4f0bdeSVikas Chaudhary int val; \
4481fe4f0bdeSVikas Chaudhary char *cp; \
4482fe4f0bdeSVikas Chaudhary struct iscsi_cls_session *session = \
4483fe4f0bdeSVikas Chaudhary iscsi_dev_to_session(dev->parent); \
4484fe4f0bdeSVikas Chaudhary if ((session->state == ISCSI_SESSION_FREE) || \
4485fe4f0bdeSVikas Chaudhary (session->state == ISCSI_SESSION_FAILED)) \
4486fe4f0bdeSVikas Chaudhary return -EBUSY; \
44879c8108a4SChris Leech if (strncmp(buf, "off", 3) == 0) { \
4488fe4f0bdeSVikas Chaudhary session->field = -1; \
44899c8108a4SChris Leech session->field##_sysfs_override = true; \
44909c8108a4SChris Leech } else { \
4491fe4f0bdeSVikas Chaudhary val = simple_strtoul(buf, &cp, 0); \
4492fe4f0bdeSVikas Chaudhary if (*cp != '\0' && *cp != '\n') \
4493fe4f0bdeSVikas Chaudhary return -EINVAL; \
4494fe4f0bdeSVikas Chaudhary session->field = val; \
44959c8108a4SChris Leech session->field##_sysfs_override = true; \
4496fe4f0bdeSVikas Chaudhary } \
4497fe4f0bdeSVikas Chaudhary return count; \
4498fe4f0bdeSVikas Chaudhary }
4499fe4f0bdeSVikas Chaudhary
4500fe4f0bdeSVikas Chaudhary #define iscsi_priv_session_rw_attr(field, format) \
4501fd7255f5SMike Christie iscsi_priv_session_attr_show(field, format) \
4502fe4f0bdeSVikas Chaudhary iscsi_priv_session_attr_store(field) \
4503523f3c80SVasiliy Kulikov static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR, \
4504fe4f0bdeSVikas Chaudhary show_priv_session_##field, \
4505fe4f0bdeSVikas Chaudhary store_priv_session_##field)
45069c8108a4SChris Leech
4507fe4f0bdeSVikas Chaudhary iscsi_priv_session_rw_attr(recovery_tmo, "%d");
4508fd7255f5SMike Christie
45091d063c17SMike Christie static struct attribute *iscsi_session_attrs[] = {
45101d063c17SMike Christie &dev_attr_sess_initial_r2t.attr,
45111d063c17SMike Christie &dev_attr_sess_max_outstanding_r2t.attr,
45121d063c17SMike Christie &dev_attr_sess_immediate_data.attr,
45131d063c17SMike Christie &dev_attr_sess_first_burst_len.attr,
45141d063c17SMike Christie &dev_attr_sess_max_burst_len.attr,
45151d063c17SMike Christie &dev_attr_sess_data_pdu_in_order.attr,
45161d063c17SMike Christie &dev_attr_sess_data_seq_in_order.attr,
45171d063c17SMike Christie &dev_attr_sess_erl.attr,
45181d063c17SMike Christie &dev_attr_sess_targetname.attr,
45191d063c17SMike Christie &dev_attr_sess_tpgt.attr,
45201d063c17SMike Christie &dev_attr_sess_password.attr,
45211d063c17SMike Christie &dev_attr_sess_password_in.attr,
45221d063c17SMike Christie &dev_attr_sess_username.attr,
45231d063c17SMike Christie &dev_attr_sess_username_in.attr,
45241d063c17SMike Christie &dev_attr_sess_fast_abort.attr,
45251d063c17SMike Christie &dev_attr_sess_abort_tmo.attr,
45261d063c17SMike Christie &dev_attr_sess_lu_reset_tmo.attr,
45271d063c17SMike Christie &dev_attr_sess_tgt_reset_tmo.attr,
45281d063c17SMike Christie &dev_attr_sess_ifacename.attr,
45291d063c17SMike Christie &dev_attr_sess_initiatorname.attr,
45301d063c17SMike Christie &dev_attr_sess_targetalias.attr,
45313b9373e9SEddie Wai &dev_attr_sess_boot_root.attr,
45323b9373e9SEddie Wai &dev_attr_sess_boot_nic.attr,
45333b9373e9SEddie Wai &dev_attr_sess_boot_target.attr,
45341d063c17SMike Christie &dev_attr_priv_sess_recovery_tmo.attr,
45351d063c17SMike Christie &dev_attr_priv_sess_state.attr,
4536a3be19b9SWenchao Hao &dev_attr_priv_sess_target_state.attr,
45370c70d84bSMike Christie &dev_attr_priv_sess_creator.attr,
453830534952SMike Christie &dev_attr_sess_chap_out_idx.attr,
453930534952SMike Christie &dev_attr_sess_chap_in_idx.attr,
4540930a9f04SManish Rangankar &dev_attr_priv_sess_target_id.attr,
4541ae542edbSAdheer Chandravanshi &dev_attr_sess_auto_snd_tgt_disable.attr,
4542ae542edbSAdheer Chandravanshi &dev_attr_sess_discovery_session.attr,
4543ae542edbSAdheer Chandravanshi &dev_attr_sess_portal_type.attr,
4544ae542edbSAdheer Chandravanshi &dev_attr_sess_chap_auth.attr,
4545ae542edbSAdheer Chandravanshi &dev_attr_sess_discovery_logout.attr,
4546ae542edbSAdheer Chandravanshi &dev_attr_sess_bidi_chap.attr,
4547ae542edbSAdheer Chandravanshi &dev_attr_sess_discovery_auth_optional.attr,
4548ae542edbSAdheer Chandravanshi &dev_attr_sess_def_time2wait.attr,
4549ae542edbSAdheer Chandravanshi &dev_attr_sess_def_time2retain.attr,
4550ae542edbSAdheer Chandravanshi &dev_attr_sess_isid.attr,
4551ae542edbSAdheer Chandravanshi &dev_attr_sess_tsid.attr,
4552ae542edbSAdheer Chandravanshi &dev_attr_sess_def_taskmgmt_tmo.attr,
4553ae542edbSAdheer Chandravanshi &dev_attr_sess_discovery_parent_idx.attr,
4554ae542edbSAdheer Chandravanshi &dev_attr_sess_discovery_parent_type.attr,
45551d063c17SMike Christie NULL,
45561d063c17SMike Christie };
45571d063c17SMike Christie
iscsi_session_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)4558587a1f16SAl Viro static umode_t iscsi_session_attr_is_visible(struct kobject *kobj,
45591d063c17SMike Christie struct attribute *attr, int i)
45601d063c17SMike Christie {
45611d063c17SMike Christie struct device *cdev = container_of(kobj, struct device, kobj);
45621d063c17SMike Christie struct iscsi_cls_session *session = transport_class_to_session(cdev);
45631d063c17SMike Christie struct iscsi_transport *t = session->transport;
45641d063c17SMike Christie int param;
45651d063c17SMike Christie
45661d063c17SMike Christie if (attr == &dev_attr_sess_initial_r2t.attr)
45671d063c17SMike Christie param = ISCSI_PARAM_INITIAL_R2T_EN;
45681d063c17SMike Christie else if (attr == &dev_attr_sess_max_outstanding_r2t.attr)
45691d063c17SMike Christie param = ISCSI_PARAM_MAX_R2T;
45701d063c17SMike Christie else if (attr == &dev_attr_sess_immediate_data.attr)
45711d063c17SMike Christie param = ISCSI_PARAM_IMM_DATA_EN;
45721d063c17SMike Christie else if (attr == &dev_attr_sess_first_burst_len.attr)
45731d063c17SMike Christie param = ISCSI_PARAM_FIRST_BURST;
45741d063c17SMike Christie else if (attr == &dev_attr_sess_max_burst_len.attr)
45751d063c17SMike Christie param = ISCSI_PARAM_MAX_BURST;
45761d063c17SMike Christie else if (attr == &dev_attr_sess_data_pdu_in_order.attr)
45771d063c17SMike Christie param = ISCSI_PARAM_PDU_INORDER_EN;
45781d063c17SMike Christie else if (attr == &dev_attr_sess_data_seq_in_order.attr)
45791d063c17SMike Christie param = ISCSI_PARAM_DATASEQ_INORDER_EN;
45801d063c17SMike Christie else if (attr == &dev_attr_sess_erl.attr)
45811d063c17SMike Christie param = ISCSI_PARAM_ERL;
45821d063c17SMike Christie else if (attr == &dev_attr_sess_targetname.attr)
45831d063c17SMike Christie param = ISCSI_PARAM_TARGET_NAME;
45841d063c17SMike Christie else if (attr == &dev_attr_sess_tpgt.attr)
45851d063c17SMike Christie param = ISCSI_PARAM_TPGT;
458630534952SMike Christie else if (attr == &dev_attr_sess_chap_in_idx.attr)
458730534952SMike Christie param = ISCSI_PARAM_CHAP_IN_IDX;
458830534952SMike Christie else if (attr == &dev_attr_sess_chap_out_idx.attr)
458930534952SMike Christie param = ISCSI_PARAM_CHAP_OUT_IDX;
45901d063c17SMike Christie else if (attr == &dev_attr_sess_password.attr)
45911d063c17SMike Christie param = ISCSI_PARAM_USERNAME;
45921d063c17SMike Christie else if (attr == &dev_attr_sess_password_in.attr)
45931d063c17SMike Christie param = ISCSI_PARAM_USERNAME_IN;
45941d063c17SMike Christie else if (attr == &dev_attr_sess_username.attr)
45951d063c17SMike Christie param = ISCSI_PARAM_PASSWORD;
45961d063c17SMike Christie else if (attr == &dev_attr_sess_username_in.attr)
45971d063c17SMike Christie param = ISCSI_PARAM_PASSWORD_IN;
45981d063c17SMike Christie else if (attr == &dev_attr_sess_fast_abort.attr)
45991d063c17SMike Christie param = ISCSI_PARAM_FAST_ABORT;
46001d063c17SMike Christie else if (attr == &dev_attr_sess_abort_tmo.attr)
46011d063c17SMike Christie param = ISCSI_PARAM_ABORT_TMO;
46021d063c17SMike Christie else if (attr == &dev_attr_sess_lu_reset_tmo.attr)
46031d063c17SMike Christie param = ISCSI_PARAM_LU_RESET_TMO;
46041d063c17SMike Christie else if (attr == &dev_attr_sess_tgt_reset_tmo.attr)
46051d063c17SMike Christie param = ISCSI_PARAM_TGT_RESET_TMO;
46061d063c17SMike Christie else if (attr == &dev_attr_sess_ifacename.attr)
46071d063c17SMike Christie param = ISCSI_PARAM_IFACE_NAME;
46081d063c17SMike Christie else if (attr == &dev_attr_sess_initiatorname.attr)
46091d063c17SMike Christie param = ISCSI_PARAM_INITIATOR_NAME;
46101d063c17SMike Christie else if (attr == &dev_attr_sess_targetalias.attr)
46111d063c17SMike Christie param = ISCSI_PARAM_TARGET_ALIAS;
46123b9373e9SEddie Wai else if (attr == &dev_attr_sess_boot_root.attr)
46133b9373e9SEddie Wai param = ISCSI_PARAM_BOOT_ROOT;
46143b9373e9SEddie Wai else if (attr == &dev_attr_sess_boot_nic.attr)
46153b9373e9SEddie Wai param = ISCSI_PARAM_BOOT_NIC;
46163b9373e9SEddie Wai else if (attr == &dev_attr_sess_boot_target.attr)
46173b9373e9SEddie Wai param = ISCSI_PARAM_BOOT_TARGET;
4618ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_auto_snd_tgt_disable.attr)
4619ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_AUTO_SND_TGT_DISABLE;
4620ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_discovery_session.attr)
4621ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_DISCOVERY_SESS;
4622ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_portal_type.attr)
4623ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_PORTAL_TYPE;
4624ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_chap_auth.attr)
4625ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_CHAP_AUTH_EN;
4626ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_discovery_logout.attr)
4627ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_DISCOVERY_LOGOUT_EN;
4628ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_bidi_chap.attr)
4629ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_BIDI_CHAP_EN;
4630ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_discovery_auth_optional.attr)
4631ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_DISCOVERY_AUTH_OPTIONAL;
4632ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_def_time2wait.attr)
4633ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_DEF_TIME2WAIT;
4634ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_def_time2retain.attr)
4635ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_DEF_TIME2RETAIN;
4636ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_isid.attr)
4637ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_ISID;
4638ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_tsid.attr)
4639ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_TSID;
4640ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_def_taskmgmt_tmo.attr)
4641ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_DEF_TASKMGMT_TMO;
4642ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_discovery_parent_idx.attr)
4643ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_DISCOVERY_PARENT_IDX;
4644ae542edbSAdheer Chandravanshi else if (attr == &dev_attr_sess_discovery_parent_type.attr)
4645ae542edbSAdheer Chandravanshi param = ISCSI_PARAM_DISCOVERY_PARENT_TYPE;
46461d063c17SMike Christie else if (attr == &dev_attr_priv_sess_recovery_tmo.attr)
46471d063c17SMike Christie return S_IRUGO | S_IWUSR;
46481d063c17SMike Christie else if (attr == &dev_attr_priv_sess_state.attr)
46491d063c17SMike Christie return S_IRUGO;
4650a3be19b9SWenchao Hao else if (attr == &dev_attr_priv_sess_target_state.attr)
4651a3be19b9SWenchao Hao return S_IRUGO;
46520c70d84bSMike Christie else if (attr == &dev_attr_priv_sess_creator.attr)
46530c70d84bSMike Christie return S_IRUGO;
4654930a9f04SManish Rangankar else if (attr == &dev_attr_priv_sess_target_id.attr)
4655930a9f04SManish Rangankar return S_IRUGO;
46561d063c17SMike Christie else {
46571d063c17SMike Christie WARN_ONCE(1, "Invalid session attr");
46581d063c17SMike Christie return 0;
46591d063c17SMike Christie }
46601d063c17SMike Christie
46611d063c17SMike Christie return t->attr_is_visible(ISCSI_PARAM, param);
46621d063c17SMike Christie }
46631d063c17SMike Christie
46641d063c17SMike Christie static struct attribute_group iscsi_session_group = {
46651d063c17SMike Christie .attrs = iscsi_session_attrs,
46661d063c17SMike Christie .is_visible = iscsi_session_attr_is_visible,
46671d063c17SMike Christie };
46681d063c17SMike Christie
46691819dc81SMike Christie /*
46701819dc81SMike Christie * iSCSI host attrs
46711819dc81SMike Christie */
46721819dc81SMike Christie #define iscsi_host_attr_show(param) \
46731819dc81SMike Christie static ssize_t \
4674ee959b00STony Jones show_host_param_##param(struct device *dev, \
4675ee959b00STony Jones struct device_attribute *attr, char *buf) \
46761819dc81SMike Christie { \
4677ee959b00STony Jones struct Scsi_Host *shost = transport_class_to_shost(dev); \
46781819dc81SMike Christie struct iscsi_internal *priv = to_iscsi_internal(shost->transportt); \
46791819dc81SMike Christie return priv->iscsi_transport->get_host_param(shost, param, buf); \
46801819dc81SMike Christie }
46811819dc81SMike Christie
46821819dc81SMike Christie #define iscsi_host_attr(field, param) \
46831819dc81SMike Christie iscsi_host_attr_show(param) \
46841819dc81SMike Christie static ISCSI_CLASS_ATTR(host, field, S_IRUGO, show_host_param_##param, \
46851819dc81SMike Christie NULL);
46861819dc81SMike Christie
4687d8196ed2SMike Christie iscsi_host_attr(netdev, ISCSI_HOST_PARAM_NETDEV_NAME);
46881819dc81SMike Christie iscsi_host_attr(hwaddress, ISCSI_HOST_PARAM_HWADDRESS);
4689d8196ed2SMike Christie iscsi_host_attr(ipaddress, ISCSI_HOST_PARAM_IPADDRESS);
46908ad5781aSMike Christie iscsi_host_attr(initiatorname, ISCSI_HOST_PARAM_INITIATOR_NAME);
4691aeddde29SVikas Chaudhary iscsi_host_attr(port_state, ISCSI_HOST_PARAM_PORT_STATE);
4692aeddde29SVikas Chaudhary iscsi_host_attr(port_speed, ISCSI_HOST_PARAM_PORT_SPEED);
46931819dc81SMike Christie
4694f27fb2efSMike Christie static struct attribute *iscsi_host_attrs[] = {
4695f27fb2efSMike Christie &dev_attr_host_netdev.attr,
4696f27fb2efSMike Christie &dev_attr_host_hwaddress.attr,
4697f27fb2efSMike Christie &dev_attr_host_ipaddress.attr,
4698f27fb2efSMike Christie &dev_attr_host_initiatorname.attr,
4699aeddde29SVikas Chaudhary &dev_attr_host_port_state.attr,
4700aeddde29SVikas Chaudhary &dev_attr_host_port_speed.attr,
4701f27fb2efSMike Christie NULL,
4702f27fb2efSMike Christie };
4703f27fb2efSMike Christie
iscsi_host_attr_is_visible(struct kobject * kobj,struct attribute * attr,int i)4704587a1f16SAl Viro static umode_t iscsi_host_attr_is_visible(struct kobject *kobj,
4705f27fb2efSMike Christie struct attribute *attr, int i)
4706f27fb2efSMike Christie {
4707f27fb2efSMike Christie struct device *cdev = container_of(kobj, struct device, kobj);
4708f27fb2efSMike Christie struct Scsi_Host *shost = transport_class_to_shost(cdev);
4709f27fb2efSMike Christie struct iscsi_internal *priv = to_iscsi_internal(shost->transportt);
4710f27fb2efSMike Christie int param;
4711f27fb2efSMike Christie
4712f27fb2efSMike Christie if (attr == &dev_attr_host_netdev.attr)
4713f27fb2efSMike Christie param = ISCSI_HOST_PARAM_NETDEV_NAME;
4714f27fb2efSMike Christie else if (attr == &dev_attr_host_hwaddress.attr)
4715f27fb2efSMike Christie param = ISCSI_HOST_PARAM_HWADDRESS;
4716f27fb2efSMike Christie else if (attr == &dev_attr_host_ipaddress.attr)
4717f27fb2efSMike Christie param = ISCSI_HOST_PARAM_IPADDRESS;
4718f27fb2efSMike Christie else if (attr == &dev_attr_host_initiatorname.attr)
4719f27fb2efSMike Christie param = ISCSI_HOST_PARAM_INITIATOR_NAME;
4720aeddde29SVikas Chaudhary else if (attr == &dev_attr_host_port_state.attr)
4721aeddde29SVikas Chaudhary param = ISCSI_HOST_PARAM_PORT_STATE;
4722aeddde29SVikas Chaudhary else if (attr == &dev_attr_host_port_speed.attr)
4723aeddde29SVikas Chaudhary param = ISCSI_HOST_PARAM_PORT_SPEED;
4724f27fb2efSMike Christie else {
4725f27fb2efSMike Christie WARN_ONCE(1, "Invalid host attr");
4726f27fb2efSMike Christie return 0;
4727f27fb2efSMike Christie }
4728f27fb2efSMike Christie
4729f27fb2efSMike Christie return priv->iscsi_transport->attr_is_visible(ISCSI_HOST_PARAM, param);
4730f27fb2efSMike Christie }
4731f27fb2efSMike Christie
4732f27fb2efSMike Christie static struct attribute_group iscsi_host_group = {
4733f27fb2efSMike Christie .attrs = iscsi_host_attrs,
4734f27fb2efSMike Christie .is_visible = iscsi_host_attr_is_visible,
4735f27fb2efSMike Christie };
47361819dc81SMike Christie
4737aeddde29SVikas Chaudhary /* convert iscsi_port_speed values to ascii string name */
4738aeddde29SVikas Chaudhary static const struct {
4739aeddde29SVikas Chaudhary enum iscsi_port_speed value;
4740aeddde29SVikas Chaudhary char *name;
4741aeddde29SVikas Chaudhary } iscsi_port_speed_names[] = {
4742aeddde29SVikas Chaudhary {ISCSI_PORT_SPEED_UNKNOWN, "Unknown" },
4743aeddde29SVikas Chaudhary {ISCSI_PORT_SPEED_10MBPS, "10 Mbps" },
4744aeddde29SVikas Chaudhary {ISCSI_PORT_SPEED_100MBPS, "100 Mbps" },
4745aeddde29SVikas Chaudhary {ISCSI_PORT_SPEED_1GBPS, "1 Gbps" },
4746aeddde29SVikas Chaudhary {ISCSI_PORT_SPEED_10GBPS, "10 Gbps" },
4747f9e4fa46SJitendra Bhivare {ISCSI_PORT_SPEED_25GBPS, "25 Gbps" },
4748f9e4fa46SJitendra Bhivare {ISCSI_PORT_SPEED_40GBPS, "40 Gbps" },
4749aeddde29SVikas Chaudhary };
4750aeddde29SVikas Chaudhary
iscsi_get_port_speed_name(struct Scsi_Host * shost)4751aeddde29SVikas Chaudhary char *iscsi_get_port_speed_name(struct Scsi_Host *shost)
4752aeddde29SVikas Chaudhary {
4753aeddde29SVikas Chaudhary int i;
4754aeddde29SVikas Chaudhary char *speed = "Unknown!";
4755aeddde29SVikas Chaudhary struct iscsi_cls_host *ihost = shost->shost_data;
4756aeddde29SVikas Chaudhary uint32_t port_speed = ihost->port_speed;
4757aeddde29SVikas Chaudhary
4758aeddde29SVikas Chaudhary for (i = 0; i < ARRAY_SIZE(iscsi_port_speed_names); i++) {
4759aeddde29SVikas Chaudhary if (iscsi_port_speed_names[i].value & port_speed) {
4760aeddde29SVikas Chaudhary speed = iscsi_port_speed_names[i].name;
4761aeddde29SVikas Chaudhary break;
4762aeddde29SVikas Chaudhary }
4763aeddde29SVikas Chaudhary }
4764aeddde29SVikas Chaudhary return speed;
4765aeddde29SVikas Chaudhary }
4766aeddde29SVikas Chaudhary EXPORT_SYMBOL_GPL(iscsi_get_port_speed_name);
4767aeddde29SVikas Chaudhary
4768aeddde29SVikas Chaudhary /* convert iscsi_port_state values to ascii string name */
4769aeddde29SVikas Chaudhary static const struct {
4770aeddde29SVikas Chaudhary enum iscsi_port_state value;
4771aeddde29SVikas Chaudhary char *name;
4772aeddde29SVikas Chaudhary } iscsi_port_state_names[] = {
4773aeddde29SVikas Chaudhary {ISCSI_PORT_STATE_DOWN, "LINK DOWN" },
4774aeddde29SVikas Chaudhary {ISCSI_PORT_STATE_UP, "LINK UP" },
4775aeddde29SVikas Chaudhary };
4776aeddde29SVikas Chaudhary
iscsi_get_port_state_name(struct Scsi_Host * shost)4777aeddde29SVikas Chaudhary char *iscsi_get_port_state_name(struct Scsi_Host *shost)
4778aeddde29SVikas Chaudhary {
4779aeddde29SVikas Chaudhary int i;
4780aeddde29SVikas Chaudhary char *state = "Unknown!";
4781aeddde29SVikas Chaudhary struct iscsi_cls_host *ihost = shost->shost_data;
4782aeddde29SVikas Chaudhary uint32_t port_state = ihost->port_state;
4783aeddde29SVikas Chaudhary
4784aeddde29SVikas Chaudhary for (i = 0; i < ARRAY_SIZE(iscsi_port_state_names); i++) {
4785aeddde29SVikas Chaudhary if (iscsi_port_state_names[i].value & port_state) {
4786aeddde29SVikas Chaudhary state = iscsi_port_state_names[i].name;
4787aeddde29SVikas Chaudhary break;
4788aeddde29SVikas Chaudhary }
4789aeddde29SVikas Chaudhary }
4790aeddde29SVikas Chaudhary return state;
4791aeddde29SVikas Chaudhary }
4792aeddde29SVikas Chaudhary EXPORT_SYMBOL_GPL(iscsi_get_port_state_name);
4793aeddde29SVikas Chaudhary
iscsi_session_match(struct attribute_container * cont,struct device * dev)47940896b752SAlex Aizman static int iscsi_session_match(struct attribute_container *cont,
47950896b752SAlex Aizman struct device *dev)
47960896b752SAlex Aizman {
47977b8631b5SMike Christie struct iscsi_cls_session *session;
47980896b752SAlex Aizman struct Scsi_Host *shost;
47990896b752SAlex Aizman struct iscsi_internal *priv;
48000896b752SAlex Aizman
48010896b752SAlex Aizman if (!iscsi_is_session_dev(dev))
48020896b752SAlex Aizman return 0;
48030896b752SAlex Aizman
48047b8631b5SMike Christie session = iscsi_dev_to_session(dev);
48057b8631b5SMike Christie shost = iscsi_session_to_shost(session);
48060896b752SAlex Aizman if (!shost->transportt)
48070896b752SAlex Aizman return 0;
48080896b752SAlex Aizman
48090896b752SAlex Aizman priv = to_iscsi_internal(shost->transportt);
48100896b752SAlex Aizman if (priv->session_cont.ac.class != &iscsi_session_class.class)
48110896b752SAlex Aizman return 0;
48120896b752SAlex Aizman
48130896b752SAlex Aizman return &priv->session_cont.ac == cont;
48140896b752SAlex Aizman }
48150896b752SAlex Aizman
iscsi_conn_match(struct attribute_container * cont,struct device * dev)48160896b752SAlex Aizman static int iscsi_conn_match(struct attribute_container *cont,
48170896b752SAlex Aizman struct device *dev)
48180896b752SAlex Aizman {
48197b8631b5SMike Christie struct iscsi_cls_session *session;
48207b8631b5SMike Christie struct iscsi_cls_conn *conn;
48210896b752SAlex Aizman struct Scsi_Host *shost;
48220896b752SAlex Aizman struct iscsi_internal *priv;
48230896b752SAlex Aizman
48240896b752SAlex Aizman if (!iscsi_is_conn_dev(dev))
48250896b752SAlex Aizman return 0;
48260896b752SAlex Aizman
48277b8631b5SMike Christie conn = iscsi_dev_to_conn(dev);
48287b8631b5SMike Christie session = iscsi_dev_to_session(conn->dev.parent);
48297b8631b5SMike Christie shost = iscsi_session_to_shost(session);
48307b8631b5SMike Christie
48310896b752SAlex Aizman if (!shost->transportt)
48320896b752SAlex Aizman return 0;
48330896b752SAlex Aizman
48340896b752SAlex Aizman priv = to_iscsi_internal(shost->transportt);
48350896b752SAlex Aizman if (priv->conn_cont.ac.class != &iscsi_connection_class.class)
48360896b752SAlex Aizman return 0;
48370896b752SAlex Aizman
48380896b752SAlex Aizman return &priv->conn_cont.ac == cont;
48390896b752SAlex Aizman }
48400896b752SAlex Aizman
iscsi_host_match(struct attribute_container * cont,struct device * dev)484130a6c652SMike Christie static int iscsi_host_match(struct attribute_container *cont,
484230a6c652SMike Christie struct device *dev)
484330a6c652SMike Christie {
484430a6c652SMike Christie struct Scsi_Host *shost;
484530a6c652SMike Christie struct iscsi_internal *priv;
484630a6c652SMike Christie
484730a6c652SMike Christie if (!scsi_is_host_device(dev))
484830a6c652SMike Christie return 0;
484930a6c652SMike Christie
485030a6c652SMike Christie shost = dev_to_shost(dev);
485130a6c652SMike Christie if (!shost->transportt ||
485230a6c652SMike Christie shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
485330a6c652SMike Christie return 0;
485430a6c652SMike Christie
485530a6c652SMike Christie priv = to_iscsi_internal(shost->transportt);
485630a6c652SMike Christie return &priv->t.host_attrs.ac == cont;
485730a6c652SMike Christie }
485830a6c652SMike Christie
48597b8631b5SMike Christie struct scsi_transport_template *
iscsi_register_transport(struct iscsi_transport * tt)48607b8631b5SMike Christie iscsi_register_transport(struct iscsi_transport *tt)
48610896b752SAlex Aizman {
48620896b752SAlex Aizman struct iscsi_internal *priv;
48630896b752SAlex Aizman unsigned long flags;
4864f27fb2efSMike Christie int err;
48650896b752SAlex Aizman
48660896b752SAlex Aizman BUG_ON(!tt);
4867891e2639SMike Christie WARN_ON(tt->ep_disconnect && !tt->unbind_conn);
48680896b752SAlex Aizman
48690896b752SAlex Aizman priv = iscsi_if_transport_lookup(tt);
48700896b752SAlex Aizman if (priv)
48717b8631b5SMike Christie return NULL;
48720896b752SAlex Aizman
487324669f75SJes Sorensen priv = kzalloc(sizeof(*priv), GFP_KERNEL);
48740896b752SAlex Aizman if (!priv)
48757b8631b5SMike Christie return NULL;
48760896b752SAlex Aizman INIT_LIST_HEAD(&priv->list);
48770896b752SAlex Aizman priv->iscsi_transport = tt;
487830a6c652SMike Christie priv->t.user_scan = iscsi_user_scan;
48790896b752SAlex Aizman
4880ee959b00STony Jones priv->dev.class = &iscsi_transport_class;
488171610f55SKay Sievers dev_set_name(&priv->dev, "%s", tt->name);
4882ee959b00STony Jones err = device_register(&priv->dev);
48830896b752SAlex Aizman if (err)
4884f014165fSZhou Guanghui goto put_dev;
48850896b752SAlex Aizman
4886ee959b00STony Jones err = sysfs_create_group(&priv->dev.kobj, &iscsi_transport_group);
48870896b752SAlex Aizman if (err)
4888ee959b00STony Jones goto unregister_dev;
48890896b752SAlex Aizman
489030a6c652SMike Christie /* host parameters */
489130a6c652SMike Christie priv->t.host_attrs.ac.class = &iscsi_host_class.class;
489230a6c652SMike Christie priv->t.host_attrs.ac.match = iscsi_host_match;
4893f27fb2efSMike Christie priv->t.host_attrs.ac.grp = &iscsi_host_group;
489432c6e1b9SMike Christie priv->t.host_size = sizeof(struct iscsi_cls_host);
489530a6c652SMike Christie transport_container_register(&priv->t.host_attrs);
489630a6c652SMike Christie
48970896b752SAlex Aizman /* connection parameters */
48980896b752SAlex Aizman priv->conn_cont.ac.class = &iscsi_connection_class.class;
48990896b752SAlex Aizman priv->conn_cont.ac.match = iscsi_conn_match;
49003128c6c7SMike Christie priv->conn_cont.ac.grp = &iscsi_conn_group;
49010896b752SAlex Aizman transport_container_register(&priv->conn_cont);
49020896b752SAlex Aizman
49030896b752SAlex Aizman /* session parameters */
49040896b752SAlex Aizman priv->session_cont.ac.class = &iscsi_session_class.class;
49050896b752SAlex Aizman priv->session_cont.ac.match = iscsi_session_match;
49061d063c17SMike Christie priv->session_cont.ac.grp = &iscsi_session_group;
49070896b752SAlex Aizman transport_container_register(&priv->session_cont);
49080896b752SAlex Aizman
49090896b752SAlex Aizman spin_lock_irqsave(&iscsi_transport_lock, flags);
49100896b752SAlex Aizman list_add(&priv->list, &iscsi_transports);
49110896b752SAlex Aizman spin_unlock_irqrestore(&iscsi_transport_lock, flags);
49121da177e4SLinus Torvalds
49130896b752SAlex Aizman printk(KERN_NOTICE "iscsi: registered transport (%s)\n", tt->name);
49147b8631b5SMike Christie return &priv->t;
49151da177e4SLinus Torvalds
4916ee959b00STony Jones unregister_dev:
4917ee959b00STony Jones device_unregister(&priv->dev);
4918d82ff9beSMike Christie return NULL;
4919f014165fSZhou Guanghui put_dev:
4920f014165fSZhou Guanghui put_device(&priv->dev);
49217b8631b5SMike Christie return NULL;
49221da177e4SLinus Torvalds }
49230896b752SAlex Aizman EXPORT_SYMBOL_GPL(iscsi_register_transport);
49241da177e4SLinus Torvalds
iscsi_unregister_transport(struct iscsi_transport * tt)49256a33ed50SMax Gurtovoy void iscsi_unregister_transport(struct iscsi_transport *tt)
49261da177e4SLinus Torvalds {
49270896b752SAlex Aizman struct iscsi_internal *priv;
49280896b752SAlex Aizman unsigned long flags;
49291da177e4SLinus Torvalds
49300896b752SAlex Aizman BUG_ON(!tt);
49311da177e4SLinus Torvalds
49320b950672SArjan van de Ven mutex_lock(&rx_queue_mutex);
49330896b752SAlex Aizman
49340896b752SAlex Aizman priv = iscsi_if_transport_lookup(tt);
49350896b752SAlex Aizman BUG_ON (!priv);
49360896b752SAlex Aizman
49370896b752SAlex Aizman spin_lock_irqsave(&iscsi_transport_lock, flags);
49380896b752SAlex Aizman list_del(&priv->list);
49390896b752SAlex Aizman spin_unlock_irqrestore(&iscsi_transport_lock, flags);
49400896b752SAlex Aizman
49410896b752SAlex Aizman transport_container_unregister(&priv->conn_cont);
49420896b752SAlex Aizman transport_container_unregister(&priv->session_cont);
494330a6c652SMike Christie transport_container_unregister(&priv->t.host_attrs);
49440896b752SAlex Aizman
4945ee959b00STony Jones sysfs_remove_group(&priv->dev.kobj, &iscsi_transport_group);
4946ee959b00STony Jones device_unregister(&priv->dev);
49470b950672SArjan van de Ven mutex_unlock(&rx_queue_mutex);
49480896b752SAlex Aizman }
49490896b752SAlex Aizman EXPORT_SYMBOL_GPL(iscsi_unregister_transport);
49500896b752SAlex Aizman
iscsi_dbg_trace(void (* trace)(struct device * dev,struct va_format *),struct device * dev,const char * fmt,...)4951c2332b00SFred Herard void iscsi_dbg_trace(void (*trace)(struct device *dev, struct va_format *),
4952c2332b00SFred Herard struct device *dev, const char *fmt, ...)
4953c2332b00SFred Herard {
4954c2332b00SFred Herard struct va_format vaf;
4955c2332b00SFred Herard va_list args;
4956c2332b00SFred Herard
4957c2332b00SFred Herard va_start(args, fmt);
4958c2332b00SFred Herard vaf.fmt = fmt;
4959c2332b00SFred Herard vaf.va = &args;
4960c2332b00SFred Herard trace(dev, &vaf);
4961c2332b00SFred Herard va_end(args);
4962c2332b00SFred Herard }
4963c2332b00SFred Herard EXPORT_SYMBOL_GPL(iscsi_dbg_trace);
4964c2332b00SFred Herard
iscsi_transport_init(void)49651da177e4SLinus Torvalds static __init int iscsi_transport_init(void)
49661da177e4SLinus Torvalds {
49670896b752SAlex Aizman int err;
4968a31f2d17SPablo Neira Ayuso struct netlink_kernel_cfg cfg = {
4969a31f2d17SPablo Neira Ayuso .groups = 1,
4970a31f2d17SPablo Neira Ayuso .input = iscsi_if_rx,
4971a31f2d17SPablo Neira Ayuso };
497209492605SMeelis Roos printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
4973f4246b33SMike Christie ISCSI_TRANSPORT_VERSION);
4974f4246b33SMike Christie
497541be1444SMike Christie atomic_set(&iscsi_session_nr, 0);
497641be1444SMike Christie
49770896b752SAlex Aizman err = class_register(&iscsi_transport_class);
49781da177e4SLinus Torvalds if (err)
49791da177e4SLinus Torvalds return err;
49800896b752SAlex Aizman
4981d82ff9beSMike Christie err = class_register(&iscsi_endpoint_class);
49820896b752SAlex Aizman if (err)
49830896b752SAlex Aizman goto unregister_transport_class;
49840896b752SAlex Aizman
49858d07913dSMike Christie err = class_register(&iscsi_iface_class);
4986d82ff9beSMike Christie if (err)
4987d82ff9beSMike Christie goto unregister_endpoint_class;
4988d82ff9beSMike Christie
49898d07913dSMike Christie err = transport_class_register(&iscsi_host_class);
49908d07913dSMike Christie if (err)
49918d07913dSMike Christie goto unregister_iface_class;
49928d07913dSMike Christie
499330a6c652SMike Christie err = transport_class_register(&iscsi_connection_class);
499430a6c652SMike Christie if (err)
499530a6c652SMike Christie goto unregister_host_class;
499630a6c652SMike Christie
49970896b752SAlex Aizman err = transport_class_register(&iscsi_session_class);
49980896b752SAlex Aizman if (err)
49990896b752SAlex Aizman goto unregister_conn_class;
50000896b752SAlex Aizman
5001c6a4bb2eSAdheer Chandravanshi err = bus_register(&iscsi_flashnode_bus);
5002c6a4bb2eSAdheer Chandravanshi if (err)
5003c6a4bb2eSAdheer Chandravanshi goto unregister_session_class;
5004c6a4bb2eSAdheer Chandravanshi
50059f00d977SPablo Neira Ayuso nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, &cfg);
50060896b752SAlex Aizman if (!nls) {
50070896b752SAlex Aizman err = -ENOBUFS;
5008c6a4bb2eSAdheer Chandravanshi goto unregister_flashnode_bus;
50090896b752SAlex Aizman }
50100896b752SAlex Aizman
501123d6fefbSMike Christie iscsi_conn_cleanup_workq = alloc_workqueue("%s",
501223d6fefbSMike Christie WQ_SYSFS | WQ_MEM_RECLAIM | WQ_UNBOUND, 0,
501323d6fefbSMike Christie "iscsi_conn_cleanup");
501423d6fefbSMike Christie if (!iscsi_conn_cleanup_workq) {
501523d6fefbSMike Christie err = -ENOMEM;
50167cb6683cSMike Christie goto release_nls;
501723d6fefbSMike Christie }
501823d6fefbSMike Christie
50190896b752SAlex Aizman return 0;
50200896b752SAlex Aizman
5021d8bf541eSMike Christie release_nls:
5022b7c6ba6eSDenis V. Lunev netlink_kernel_release(nls);
5023c6a4bb2eSAdheer Chandravanshi unregister_flashnode_bus:
5024c6a4bb2eSAdheer Chandravanshi bus_unregister(&iscsi_flashnode_bus);
50250896b752SAlex Aizman unregister_session_class:
50260896b752SAlex Aizman transport_class_unregister(&iscsi_session_class);
50270896b752SAlex Aizman unregister_conn_class:
50280896b752SAlex Aizman transport_class_unregister(&iscsi_connection_class);
502930a6c652SMike Christie unregister_host_class:
503030a6c652SMike Christie transport_class_unregister(&iscsi_host_class);
50318d07913dSMike Christie unregister_iface_class:
50328d07913dSMike Christie class_unregister(&iscsi_iface_class);
5033d82ff9beSMike Christie unregister_endpoint_class:
5034d82ff9beSMike Christie class_unregister(&iscsi_endpoint_class);
50350896b752SAlex Aizman unregister_transport_class:
50360896b752SAlex Aizman class_unregister(&iscsi_transport_class);
50370896b752SAlex Aizman return err;
50381da177e4SLinus Torvalds }
50391da177e4SLinus Torvalds
iscsi_transport_exit(void)50401da177e4SLinus Torvalds static void __exit iscsi_transport_exit(void)
50411da177e4SLinus Torvalds {
504223d6fefbSMike Christie destroy_workqueue(iscsi_conn_cleanup_workq);
5043b7c6ba6eSDenis V. Lunev netlink_kernel_release(nls);
5044c6a4bb2eSAdheer Chandravanshi bus_unregister(&iscsi_flashnode_bus);
50450896b752SAlex Aizman transport_class_unregister(&iscsi_connection_class);
50460896b752SAlex Aizman transport_class_unregister(&iscsi_session_class);
504730a6c652SMike Christie transport_class_unregister(&iscsi_host_class);
5048d82ff9beSMike Christie class_unregister(&iscsi_endpoint_class);
50498d07913dSMike Christie class_unregister(&iscsi_iface_class);
50500896b752SAlex Aizman class_unregister(&iscsi_transport_class);
50511da177e4SLinus Torvalds }
50521da177e4SLinus Torvalds
50531da177e4SLinus Torvalds module_init(iscsi_transport_init);
50541da177e4SLinus Torvalds module_exit(iscsi_transport_exit);
50551da177e4SLinus Torvalds
50560896b752SAlex Aizman MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
50570896b752SAlex Aizman "Dmitry Yusupov <dmitry_yus@yahoo.com>, "
50580896b752SAlex Aizman "Alex Aizman <itn780@yahoo.com>");
50590896b752SAlex Aizman MODULE_DESCRIPTION("iSCSI Transport Interface");
50601da177e4SLinus Torvalds MODULE_LICENSE("GPL");
5061f4246b33SMike Christie MODULE_VERSION(ISCSI_TRANSPORT_VERSION);
5062058548aeSStephen Hemminger MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_ISCSI);
5063