2 * iSCSI transport class definitions
4 * Copyright (C) IBM Corporation, 2004
5 * Copyright (C) Mike Christie, 2004
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 #include <linux/module.h>
22 #include <linux/string.h>
23 #include <linux/slab.h>
25 #include <scsi/scsi.h>
26 #include <scsi/scsi_host.h>
27 #include <scsi/scsi_device.h>
28 #include <scsi/scsi_transport.h>
29 #include <scsi/scsi_transport_iscsi.h>
31 #define ISCSI_SESSION_ATTRS 20
32 #define ISCSI_HOST_ATTRS 2
34 struct iscsi_internal {
35 struct scsi_transport_template t;
36 struct iscsi_function_template *fnt;
38 * We do not have any private or other attrs.
40 struct class_device_attribute *session_attrs[ISCSI_SESSION_ATTRS + 1];
41 struct class_device_attribute *host_attrs[ISCSI_HOST_ATTRS + 1];
44 #define to_iscsi_internal(tmpl) container_of(tmpl, struct iscsi_internal, t)
46 static DECLARE_TRANSPORT_CLASS(iscsi_transport_class,
52 static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
58 * iSCSI target and session attrs
60 #define iscsi_session_show_fn(field, format) \
63 show_session_##field(struct class_device *cdev, char *buf) \
65 struct scsi_target *starget = transport_class_to_starget(cdev); \
66 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
67 struct iscsi_internal *i = to_iscsi_internal(shost->transportt); \
69 if (i->fnt->get_##field) \
70 i->fnt->get_##field(starget); \
71 return snprintf(buf, 20, format"\n", iscsi_##field(starget)); \
74 #define iscsi_session_rd_attr(field, format) \
75 iscsi_session_show_fn(field, format) \
76 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_##field, NULL);
78 iscsi_session_rd_attr(tpgt, "%hu");
79 iscsi_session_rd_attr(tsih, "%2x");
80 iscsi_session_rd_attr(max_recv_data_segment_len, "%u");
81 iscsi_session_rd_attr(max_burst_len, "%u");
82 iscsi_session_rd_attr(first_burst_len, "%u");
83 iscsi_session_rd_attr(def_time2wait, "%hu");
84 iscsi_session_rd_attr(def_time2retain, "%hu");
85 iscsi_session_rd_attr(max_outstanding_r2t, "%hu");
86 iscsi_session_rd_attr(erl, "%d");
89 #define iscsi_session_show_bool_fn(field) \
92 show_session_bool_##field(struct class_device *cdev, char *buf) \
94 struct scsi_target *starget = transport_class_to_starget(cdev); \
95 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
96 struct iscsi_internal *i = to_iscsi_internal(shost->transportt); \
98 if (i->fnt->get_##field) \
99 i->fnt->get_##field(starget); \
101 if (iscsi_##field(starget)) \
102 return sprintf(buf, "Yes\n"); \
103 return sprintf(buf, "No\n"); \
106 #define iscsi_session_rd_bool_attr(field) \
107 iscsi_session_show_bool_fn(field) \
108 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_bool_##field, NULL);
110 iscsi_session_rd_bool_attr(initial_r2t);
111 iscsi_session_rd_bool_attr(immediate_data);
112 iscsi_session_rd_bool_attr(data_pdu_in_order);
113 iscsi_session_rd_bool_attr(data_sequence_in_order);
115 #define iscsi_session_show_digest_fn(field) \
118 show_##field(struct class_device *cdev, char *buf) \
120 struct scsi_target *starget = transport_class_to_starget(cdev); \
121 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
122 struct iscsi_internal *i = to_iscsi_internal(shost->transportt); \
124 if (i->fnt->get_##field) \
125 i->fnt->get_##field(starget); \
127 if (iscsi_##field(starget)) \
128 return sprintf(buf, "CRC32C\n"); \
129 return sprintf(buf, "None\n"); \
132 #define iscsi_session_rd_digest_attr(field) \
133 iscsi_session_show_digest_fn(field) \
134 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
136 iscsi_session_rd_digest_attr(header_digest);
137 iscsi_session_rd_digest_attr(data_digest);
140 show_port(struct class_device *cdev, char *buf)
142 struct scsi_target *starget = transport_class_to_starget(cdev);
143 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
144 struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
146 if (i->fnt->get_port)
147 i->fnt->get_port(starget);
149 return snprintf(buf, 20, "%hu\n", ntohs(iscsi_port(starget)));
151 static CLASS_DEVICE_ATTR(port, S_IRUGO, show_port, NULL);
154 show_ip_address(struct class_device *cdev, char *buf)
156 struct scsi_target *starget = transport_class_to_starget(cdev);
157 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
158 struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
160 if (i->fnt->get_ip_address)
161 i->fnt->get_ip_address(starget);
163 if (iscsi_addr_type(starget) == AF_INET)
164 return sprintf(buf, "%u.%u.%u.%u\n",
165 NIPQUAD(iscsi_sin_addr(starget)));
166 else if(iscsi_addr_type(starget) == AF_INET6)
167 return sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
168 NIP6(iscsi_sin6_addr(starget)));
171 static CLASS_DEVICE_ATTR(ip_address, S_IRUGO, show_ip_address, NULL);
174 show_isid(struct class_device *cdev, char *buf)
176 struct scsi_target *starget = transport_class_to_starget(cdev);
177 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
178 struct iscsi_internal *i = to_iscsi_internal(shost->transportt);
180 if (i->fnt->get_isid)
181 i->fnt->get_isid(starget);
183 return sprintf(buf, "%02x%02x%02x%02x%02x%02x\n",
184 iscsi_isid(starget)[0], iscsi_isid(starget)[1],
185 iscsi_isid(starget)[2], iscsi_isid(starget)[3],
186 iscsi_isid(starget)[4], iscsi_isid(starget)[5]);
188 static CLASS_DEVICE_ATTR(isid, S_IRUGO, show_isid, NULL);
191 * This is used for iSCSI names. Normally, we follow
192 * the transport class convention of having the lld
193 * set the field, but in these cases the value is
196 #define iscsi_session_show_str_fn(field) \
199 show_session_str_##field(struct class_device *cdev, char *buf) \
202 struct scsi_target *starget = transport_class_to_starget(cdev); \
203 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); \
204 struct iscsi_internal *i = to_iscsi_internal(shost->transportt); \
206 if (i->fnt->get_##field) \
207 ret = i->fnt->get_##field(starget, buf, PAGE_SIZE); \
211 #define iscsi_session_rd_str_attr(field) \
212 iscsi_session_show_str_fn(field) \
213 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_session_str_##field, NULL);
215 iscsi_session_rd_str_attr(target_name);
216 iscsi_session_rd_str_attr(target_alias);
223 * Again, this is used for iSCSI names. Normally, we follow
224 * the transport class convention of having the lld set
225 * the field, but in these cases the value is too large.
227 #define iscsi_host_show_str_fn(field) \
230 show_host_str_##field(struct class_device *cdev, char *buf) \
233 struct Scsi_Host *shost = transport_class_to_shost(cdev); \
234 struct iscsi_internal *i = to_iscsi_internal(shost->transportt); \
236 if (i->fnt->get_##field) \
237 ret = i->fnt->get_##field(shost, buf, PAGE_SIZE); \
241 #define iscsi_host_rd_str_attr(field) \
242 iscsi_host_show_str_fn(field) \
243 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_host_str_##field, NULL);
245 iscsi_host_rd_str_attr(initiator_name);
246 iscsi_host_rd_str_attr(initiator_alias);
248 #define SETUP_SESSION_RD_ATTR(field) \
249 if (i->fnt->show_##field) { \
250 i->session_attrs[count] = &class_device_attr_##field; \
254 #define SETUP_HOST_RD_ATTR(field) \
255 if (i->fnt->show_##field) { \
256 i->host_attrs[count] = &class_device_attr_##field; \
260 static int iscsi_host_match(struct attribute_container *cont,
263 struct Scsi_Host *shost;
264 struct iscsi_internal *i;
266 if (!scsi_is_host_device(dev))
269 shost = dev_to_shost(dev);
270 if (!shost->transportt || shost->transportt->host_attrs.ac.class
271 != &iscsi_host_class.class)
274 i = to_iscsi_internal(shost->transportt);
276 return &i->t.host_attrs.ac == cont;
279 static int iscsi_target_match(struct attribute_container *cont,
282 struct Scsi_Host *shost;
283 struct iscsi_internal *i;
285 if (!scsi_is_target_device(dev))
288 shost = dev_to_shost(dev->parent);
289 if (!shost->transportt || shost->transportt->host_attrs.ac.class
290 != &iscsi_host_class.class)
293 i = to_iscsi_internal(shost->transportt);
295 return &i->t.target_attrs.ac == cont;
298 struct scsi_transport_template *
299 iscsi_attach_transport(struct iscsi_function_template *fnt)
301 struct iscsi_internal *i = kmalloc(sizeof(struct iscsi_internal),
308 memset(i, 0, sizeof(struct iscsi_internal));
311 i->t.target_attrs.ac.attrs = &i->session_attrs[0];
312 i->t.target_attrs.ac.class = &iscsi_transport_class.class;
313 i->t.target_attrs.ac.match = iscsi_target_match;
314 transport_container_register(&i->t.target_attrs);
315 i->t.target_size = sizeof(struct iscsi_class_session);
317 SETUP_SESSION_RD_ATTR(tsih);
318 SETUP_SESSION_RD_ATTR(isid);
319 SETUP_SESSION_RD_ATTR(header_digest);
320 SETUP_SESSION_RD_ATTR(data_digest);
321 SETUP_SESSION_RD_ATTR(target_name);
322 SETUP_SESSION_RD_ATTR(target_alias);
323 SETUP_SESSION_RD_ATTR(port);
324 SETUP_SESSION_RD_ATTR(tpgt);
325 SETUP_SESSION_RD_ATTR(ip_address);
326 SETUP_SESSION_RD_ATTR(initial_r2t);
327 SETUP_SESSION_RD_ATTR(immediate_data);
328 SETUP_SESSION_RD_ATTR(max_recv_data_segment_len);
329 SETUP_SESSION_RD_ATTR(max_burst_len);
330 SETUP_SESSION_RD_ATTR(first_burst_len);
331 SETUP_SESSION_RD_ATTR(def_time2wait);
332 SETUP_SESSION_RD_ATTR(def_time2retain);
333 SETUP_SESSION_RD_ATTR(max_outstanding_r2t);
334 SETUP_SESSION_RD_ATTR(data_pdu_in_order);
335 SETUP_SESSION_RD_ATTR(data_sequence_in_order);
336 SETUP_SESSION_RD_ATTR(erl);
338 BUG_ON(count > ISCSI_SESSION_ATTRS);
339 i->session_attrs[count] = NULL;
341 i->t.host_attrs.ac.attrs = &i->host_attrs[0];
342 i->t.host_attrs.ac.class = &iscsi_host_class.class;
343 i->t.host_attrs.ac.match = iscsi_host_match;
344 transport_container_register(&i->t.host_attrs);
348 SETUP_HOST_RD_ATTR(initiator_name);
349 SETUP_HOST_RD_ATTR(initiator_alias);
351 BUG_ON(count > ISCSI_HOST_ATTRS);
352 i->host_attrs[count] = NULL;
357 EXPORT_SYMBOL(iscsi_attach_transport);
359 void iscsi_release_transport(struct scsi_transport_template *t)
361 struct iscsi_internal *i = to_iscsi_internal(t);
363 transport_container_unregister(&i->t.target_attrs);
364 transport_container_unregister(&i->t.host_attrs);
369 EXPORT_SYMBOL(iscsi_release_transport);
371 static __init int iscsi_transport_init(void)
373 int err = transport_class_register(&iscsi_transport_class);
377 return transport_class_register(&iscsi_host_class);
380 static void __exit iscsi_transport_exit(void)
382 transport_class_unregister(&iscsi_host_class);
383 transport_class_unregister(&iscsi_transport_class);
386 module_init(iscsi_transport_init);
387 module_exit(iscsi_transport_exit);
389 MODULE_AUTHOR("Mike Christie");
390 MODULE_DESCRIPTION("iSCSI Transport Attributes");
391 MODULE_LICENSE("GPL");