aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c190
-rw-r--r--include/scsi/iscsi_if.h2
-rw-r--r--include/scsi/scsi_transport_iscsi.h19
3 files changed, 172 insertions, 39 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index ac9d298f54e7..c3c07ccccca7 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -33,6 +33,7 @@
33#define ISCSI_SESSION_ATTRS 19 33#define ISCSI_SESSION_ATTRS 19
34#define ISCSI_CONN_ATTRS 13 34#define ISCSI_CONN_ATTRS 13
35#define ISCSI_HOST_ATTRS 4 35#define ISCSI_HOST_ATTRS 4
36
36#define ISCSI_TRANSPORT_VERSION "2.0-869" 37#define ISCSI_TRANSPORT_VERSION "2.0-869"
37 38
38struct iscsi_internal { 39struct iscsi_internal {
@@ -112,6 +113,123 @@ static struct attribute_group iscsi_transport_group = {
112 .attrs = iscsi_transport_attrs, 113 .attrs = iscsi_transport_attrs,
113}; 114};
114 115
116/*
117 * iSCSI endpoint attrs
118 */
119#define iscsi_dev_to_endpoint(_dev) \
120 container_of(_dev, struct iscsi_endpoint, dev)
121
122#define ISCSI_ATTR(_prefix,_name,_mode,_show,_store) \
123struct device_attribute dev_attr_##_prefix##_##_name = \
124 __ATTR(_name,_mode,_show,_store)
125
126static void iscsi_endpoint_release(struct device *dev)
127{
128 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
129 kfree(ep);
130}
131
132static struct class iscsi_endpoint_class = {
133 .name = "iscsi_endpoint",
134 .dev_release = iscsi_endpoint_release,
135};
136
137static ssize_t
138show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf)
139{
140 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
141 return sprintf(buf, "%u\n", ep->id);
142}
143static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL);
144
145static struct attribute *iscsi_endpoint_attrs[] = {
146 &dev_attr_ep_handle.attr,
147 NULL,
148};
149
150static struct attribute_group iscsi_endpoint_group = {
151 .attrs = iscsi_endpoint_attrs,
152};
153
154#define ISCSI_MAX_EPID -1
155
156static int iscsi_match_epid(struct device *dev, void *data)
157{
158 struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev);
159 unsigned int *epid = (unsigned int *) data;
160
161 return *epid == ep->id;
162}
163
164struct iscsi_endpoint *
165iscsi_create_endpoint(int dd_size)
166{
167 struct device *dev;
168 struct iscsi_endpoint *ep;
169 unsigned int id;
170 int err;
171
172 for (id = 1; id < ISCSI_MAX_EPID; id++) {
173 dev = class_find_device(&iscsi_endpoint_class, &id,
174 iscsi_match_epid);
175 if (!dev)
176 break;
177 }
178 if (id == ISCSI_MAX_EPID) {
179 printk(KERN_ERR "Too many connections. Max supported %u\n",
180 ISCSI_MAX_EPID - 1);
181 return NULL;
182 }
183
184 ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL);
185 if (!ep)
186 return NULL;
187
188 ep->id = id;
189 ep->dev.class = &iscsi_endpoint_class;
190 snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%u", id);
191 err = device_register(&ep->dev);
192 if (err)
193 goto free_ep;
194
195 err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group);
196 if (err)
197 goto unregister_dev;
198
199 if (dd_size)
200 ep->dd_data = &ep[1];
201 return ep;
202
203unregister_dev:
204 device_unregister(&ep->dev);
205 return NULL;
206
207free_ep:
208 kfree(ep);
209 return NULL;
210}
211EXPORT_SYMBOL_GPL(iscsi_create_endpoint);
212
213void iscsi_destroy_endpoint(struct iscsi_endpoint *ep)
214{
215 sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group);
216 device_unregister(&ep->dev);
217}
218EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint);
219
220struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle)
221{
222 struct device *dev;
223
224 dev = class_find_device(&iscsi_endpoint_class, &handle,
225 iscsi_match_epid);
226 if (!dev)
227 return NULL;
228
229 return iscsi_dev_to_endpoint(dev);
230}
231EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);
232
115static int iscsi_setup_host(struct transport_container *tc, struct device *dev, 233static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
116 struct device *cdev) 234 struct device *cdev)
117{ 235{
@@ -1094,33 +1212,16 @@ int iscsi_session_event(struct iscsi_cls_session *session,
1094EXPORT_SYMBOL_GPL(iscsi_session_event); 1212EXPORT_SYMBOL_GPL(iscsi_session_event);
1095 1213
1096static int 1214static int
1097iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev, 1215iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
1098 uint32_t host_no, uint32_t initial_cmdsn, 1216 struct iscsi_uevent *ev, uint32_t initial_cmdsn,
1099 uint16_t cmds_max, uint16_t queue_depth) 1217 uint16_t cmds_max, uint16_t queue_depth)
1100{ 1218{
1101 struct iscsi_transport *transport = priv->iscsi_transport; 1219 struct iscsi_transport *transport = priv->iscsi_transport;
1102 struct iscsi_cls_session *session; 1220 struct iscsi_cls_session *session;
1103 struct Scsi_Host *shost = NULL; 1221 uint32_t host_no;
1104 1222
1105 /* 1223 session = transport->create_session(ep, cmds_max, queue_depth,
1106 * Software iscsi allocates a host per session, but
1107 * offload drivers (and possibly iser one day) allocate a host per
1108 * hba/nic/rnic. Offload will match a host here, but software will
1109 * return a new hostno after the create_session callback has returned.
1110 */
1111 if (host_no != UINT_MAX) {
1112 shost = scsi_host_lookup(host_no);
1113 if (IS_ERR(shost)) {
1114 printk(KERN_ERR "Could not find host no %u to "
1115 "create session\n", host_no);
1116 return -ENODEV;
1117 }
1118 }
1119
1120 session = transport->create_session(shost, cmds_max, queue_depth,
1121 initial_cmdsn, &host_no); 1224 initial_cmdsn, &host_no);
1122 if (shost)
1123 scsi_host_put(shost);
1124 if (!session) 1225 if (!session)
1125 return -ENOMEM; 1226 return -ENOMEM;
1126 1227
@@ -1199,6 +1300,7 @@ static int
1199iscsi_if_transport_ep(struct iscsi_transport *transport, 1300iscsi_if_transport_ep(struct iscsi_transport *transport,
1200 struct iscsi_uevent *ev, int msg_type) 1301 struct iscsi_uevent *ev, int msg_type)
1201{ 1302{
1303 struct iscsi_endpoint *ep;
1202 struct sockaddr *dst_addr; 1304 struct sockaddr *dst_addr;
1203 int rc = 0; 1305 int rc = 0;
1204 1306
@@ -1208,22 +1310,33 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,
1208 return -EINVAL; 1310 return -EINVAL;
1209 1311
1210 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); 1312 dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev));
1211 rc = transport->ep_connect(dst_addr, 1313 ep = transport->ep_connect(dst_addr,
1212 ev->u.ep_connect.non_blocking, 1314 ev->u.ep_connect.non_blocking);
1213 &ev->r.ep_connect_ret.handle); 1315 if (IS_ERR(ep))
1316 return PTR_ERR(ep);
1317
1318 ev->r.ep_connect_ret.handle = ep->id;
1214 break; 1319 break;
1215 case ISCSI_UEVENT_TRANSPORT_EP_POLL: 1320 case ISCSI_UEVENT_TRANSPORT_EP_POLL:
1216 if (!transport->ep_poll) 1321 if (!transport->ep_poll)
1217 return -EINVAL; 1322 return -EINVAL;
1218 1323
1219 ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle, 1324 ep = iscsi_lookup_endpoint(ev->u.ep_poll.ep_handle);
1325 if (!ep)
1326 return -EINVAL;
1327
1328 ev->r.retcode = transport->ep_poll(ep,
1220 ev->u.ep_poll.timeout_ms); 1329 ev->u.ep_poll.timeout_ms);
1221 break; 1330 break;
1222 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT: 1331 case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
1223 if (!transport->ep_disconnect) 1332 if (!transport->ep_disconnect)
1224 return -EINVAL; 1333 return -EINVAL;
1225 1334
1226 transport->ep_disconnect(ev->u.ep_disconnect.ep_handle); 1335 ep = iscsi_lookup_endpoint(ev->u.ep_disconnect.ep_handle);
1336 if (!ep)
1337 return -EINVAL;
1338
1339 transport->ep_disconnect(ep);
1227 break; 1340 break;
1228 } 1341 }
1229 return rc; 1342 return rc;
@@ -1283,12 +1396,12 @@ static int
1283iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) 1396iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1284{ 1397{
1285 int err = 0; 1398 int err = 0;
1286 uint32_t host_no = UINT_MAX;
1287 struct iscsi_uevent *ev = NLMSG_DATA(nlh); 1399 struct iscsi_uevent *ev = NLMSG_DATA(nlh);
1288 struct iscsi_transport *transport = NULL; 1400 struct iscsi_transport *transport = NULL;
1289 struct iscsi_internal *priv; 1401 struct iscsi_internal *priv;
1290 struct iscsi_cls_session *session; 1402 struct iscsi_cls_session *session;
1291 struct iscsi_cls_conn *conn; 1403 struct iscsi_cls_conn *conn;
1404 struct iscsi_endpoint *ep = NULL;
1292 1405
1293 priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle)); 1406 priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));
1294 if (!priv) 1407 if (!priv)
@@ -1302,14 +1415,17 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1302 1415
1303 switch (nlh->nlmsg_type) { 1416 switch (nlh->nlmsg_type) {
1304 case ISCSI_UEVENT_CREATE_SESSION: 1417 case ISCSI_UEVENT_CREATE_SESSION:
1305 err = iscsi_if_create_session(priv, ev, host_no, 1418 err = iscsi_if_create_session(priv, ep, ev,
1306 ev->u.c_session.initial_cmdsn, 1419 ev->u.c_session.initial_cmdsn,
1307 ev->u.c_session.cmds_max, 1420 ev->u.c_session.cmds_max,
1308 ev->u.c_session.queue_depth); 1421 ev->u.c_session.queue_depth);
1309 break; 1422 break;
1310 case ISCSI_UEVENT_CREATE_BOUND_SESSION: 1423 case ISCSI_UEVENT_CREATE_BOUND_SESSION:
1311 err = iscsi_if_create_session(priv, ev, 1424 ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle);
1312 ev->u.c_bound_session.host_no, 1425 if (!ep)
1426 return -EINVAL;
1427
1428 err = iscsi_if_create_session(priv, ep, ev,
1313 ev->u.c_bound_session.initial_cmdsn, 1429 ev->u.c_bound_session.initial_cmdsn,
1314 ev->u.c_bound_session.cmds_max, 1430 ev->u.c_bound_session.cmds_max,
1315 ev->u.c_bound_session.queue_depth); 1431 ev->u.c_bound_session.queue_depth);
@@ -1774,6 +1890,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
1774 1890
1775unregister_dev: 1891unregister_dev:
1776 device_unregister(&priv->dev); 1892 device_unregister(&priv->dev);
1893 return NULL;
1777free_priv: 1894free_priv:
1778 kfree(priv); 1895 kfree(priv);
1779 return NULL; 1896 return NULL;
@@ -1821,10 +1938,14 @@ static __init int iscsi_transport_init(void)
1821 if (err) 1938 if (err)
1822 return err; 1939 return err;
1823 1940
1824 err = transport_class_register(&iscsi_host_class); 1941 err = class_register(&iscsi_endpoint_class);
1825 if (err) 1942 if (err)
1826 goto unregister_transport_class; 1943 goto unregister_transport_class;
1827 1944
1945 err = transport_class_register(&iscsi_host_class);
1946 if (err)
1947 goto unregister_endpoint_class;
1948
1828 err = transport_class_register(&iscsi_connection_class); 1949 err = transport_class_register(&iscsi_connection_class);
1829 if (err) 1950 if (err)
1830 goto unregister_host_class; 1951 goto unregister_host_class;
@@ -1833,8 +1954,8 @@ static __init int iscsi_transport_init(void)
1833 if (err) 1954 if (err)
1834 goto unregister_conn_class; 1955 goto unregister_conn_class;
1835 1956
1836 nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL, 1957 nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx,
1837 THIS_MODULE); 1958 NULL, THIS_MODULE);
1838 if (!nls) { 1959 if (!nls) {
1839 err = -ENOBUFS; 1960 err = -ENOBUFS;
1840 goto unregister_session_class; 1961 goto unregister_session_class;
@@ -1854,6 +1975,8 @@ unregister_conn_class:
1854 transport_class_unregister(&iscsi_connection_class); 1975 transport_class_unregister(&iscsi_connection_class);
1855unregister_host_class: 1976unregister_host_class:
1856 transport_class_unregister(&iscsi_host_class); 1977 transport_class_unregister(&iscsi_host_class);
1978unregister_endpoint_class:
1979 class_unregister(&iscsi_endpoint_class);
1857unregister_transport_class: 1980unregister_transport_class:
1858 class_unregister(&iscsi_transport_class); 1981 class_unregister(&iscsi_transport_class);
1859 return err; 1982 return err;
@@ -1866,6 +1989,7 @@ static void __exit iscsi_transport_exit(void)
1866 transport_class_unregister(&iscsi_connection_class); 1989 transport_class_unregister(&iscsi_connection_class);
1867 transport_class_unregister(&iscsi_session_class); 1990 transport_class_unregister(&iscsi_session_class);
1868 transport_class_unregister(&iscsi_host_class); 1991 transport_class_unregister(&iscsi_host_class);
1992 class_unregister(&iscsi_endpoint_class);
1869 class_unregister(&iscsi_transport_class); 1993 class_unregister(&iscsi_transport_class);
1870} 1994}
1871 1995
diff --git a/include/scsi/iscsi_if.h b/include/scsi/iscsi_if.h
index 801a677777cc..a0f13a280e71 100644
--- a/include/scsi/iscsi_if.h
+++ b/include/scsi/iscsi_if.h
@@ -80,7 +80,7 @@ struct iscsi_uevent {
80 uint16_t queue_depth; 80 uint16_t queue_depth;
81 } c_session; 81 } c_session;
82 struct msg_create_bound_session { 82 struct msg_create_bound_session {
83 uint32_t host_no; 83 uint64_t ep_handle;
84 uint32_t initial_cmdsn; 84 uint32_t initial_cmdsn;
85 uint16_t cmds_max; 85 uint16_t cmds_max;
86 uint16_t queue_depth; 86 uint16_t queue_depth;
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
index d6b823195563..f5444e033cc9 100644
--- a/include/scsi/scsi_transport_iscsi.h
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -30,6 +30,7 @@
30 30
31struct scsi_transport_template; 31struct scsi_transport_template;
32struct iscsi_transport; 32struct iscsi_transport;
33struct iscsi_endpoint;
33struct Scsi_Host; 34struct Scsi_Host;
34struct iscsi_cls_conn; 35struct iscsi_cls_conn;
35struct iscsi_conn; 36struct iscsi_conn;
@@ -85,7 +86,7 @@ struct iscsi_transport {
85 /* LLD sets this to indicate what values it can export to sysfs */ 86 /* LLD sets this to indicate what values it can export to sysfs */
86 uint64_t param_mask; 87 uint64_t param_mask;
87 uint64_t host_param_mask; 88 uint64_t host_param_mask;
88 struct iscsi_cls_session *(*create_session) (struct Scsi_Host *shost, 89 struct iscsi_cls_session *(*create_session) (struct iscsi_endpoint *ep,
89 uint16_t cmds_max, uint16_t qdepth, 90 uint16_t cmds_max, uint16_t qdepth,
90 uint32_t sn, uint32_t *hn); 91 uint32_t sn, uint32_t *hn);
91 void (*destroy_session) (struct iscsi_cls_session *session); 92 void (*destroy_session) (struct iscsi_cls_session *session);
@@ -117,10 +118,10 @@ struct iscsi_transport {
117 void (*cleanup_task) (struct iscsi_conn *conn, 118 void (*cleanup_task) (struct iscsi_conn *conn,
118 struct iscsi_task *task); 119 struct iscsi_task *task);
119 void (*session_recovery_timedout) (struct iscsi_cls_session *session); 120 void (*session_recovery_timedout) (struct iscsi_cls_session *session);
120 int (*ep_connect) (struct sockaddr *dst_addr, int non_blocking, 121 struct iscsi_endpoint *(*ep_connect) (struct sockaddr *dst_addr,
121 uint64_t *ep_handle); 122 int non_blocking);
122 int (*ep_poll) (uint64_t ep_handle, int timeout_ms); 123 int (*ep_poll) (struct iscsi_endpoint *ep, int timeout_ms);
123 void (*ep_disconnect) (uint64_t ep_handle); 124 void (*ep_disconnect) (struct iscsi_endpoint *ep);
124 int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type, 125 int (*tgt_dscvr) (struct Scsi_Host *shost, enum iscsi_tgt_dscvr type,
125 uint32_t enable, struct sockaddr *dst_addr); 126 uint32_t enable, struct sockaddr *dst_addr);
126}; 127};
@@ -203,6 +204,11 @@ struct iscsi_cls_host {
203extern void iscsi_host_for_each_session(struct Scsi_Host *shost, 204extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
204 void (*fn)(struct iscsi_cls_session *)); 205 void (*fn)(struct iscsi_cls_session *));
205 206
207struct iscsi_endpoint {
208 void *dd_data; /* LLD private data */
209 struct device dev;
210 unsigned int id;
211};
206 212
207/* 213/*
208 * session and connection functions that can be used by HW iSCSI LLDs 214 * session and connection functions that can be used by HW iSCSI LLDs
@@ -233,5 +239,8 @@ extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn);
233extern void iscsi_unblock_session(struct iscsi_cls_session *session); 239extern void iscsi_unblock_session(struct iscsi_cls_session *session);
234extern void iscsi_block_session(struct iscsi_cls_session *session); 240extern void iscsi_block_session(struct iscsi_cls_session *session);
235extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time); 241extern int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time);
242extern struct iscsi_endpoint *iscsi_create_endpoint(int dd_size);
243extern void iscsi_destroy_endpoint(struct iscsi_endpoint *ep);
244extern struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle);
236 245
237#endif 246#endif