Merge branch 'upstream' of git://lost.foo-projects.org/~ahkok/git/netdev-2.6 into...
[linux-2.6] / drivers / scsi / scsi_transport_sas.c
1 /*
2  * Copyright (C) 2005-2006 Dell Inc.
3  *      Released under GPL v2.
4  *
5  * Serial Attached SCSI (SAS) transport class.
6  *
7  * The SAS transport class contains common code to deal with SAS HBAs,
8  * an aproximated representation of SAS topologies in the driver model,
9  * and various sysfs attributes to expose these topologies and managment
10  * interfaces to userspace.
11  *
12  * In addition to the basic SCSI core objects this transport class
13  * introduces two additional intermediate objects:  The SAS PHY
14  * as represented by struct sas_phy defines an "outgoing" PHY on
15  * a SAS HBA or Expander, and the SAS remote PHY represented by
16  * struct sas_rphy defines an "incoming" PHY on a SAS Expander or
17  * end device.  Note that this is purely a software concept, the
18  * underlying hardware for a PHY and a remote PHY is the exactly
19  * the same.
20  *
21  * There is no concept of a SAS port in this code, users can see
22  * what PHYs form a wide port based on the port_identifier attribute,
23  * which is the same for all PHYs in a port.
24  */
25
26 #include <linux/init.h>
27 #include <linux/module.h>
28 #include <linux/err.h>
29 #include <linux/slab.h>
30 #include <linux/string.h>
31
32 #include <scsi/scsi.h>
33 #include <scsi/scsi_device.h>
34 #include <scsi/scsi_host.h>
35 #include <scsi/scsi_transport.h>
36 #include <scsi/scsi_transport_sas.h>
37
38 #include "scsi_sas_internal.h"
39 struct sas_host_attrs {
40         struct list_head rphy_list;
41         struct mutex lock;
42         u32 next_target_id;
43         u32 next_expander_id;
44 };
45 #define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)
46
47
48 /*
49  * Hack to allow attributes of the same name in different objects.
50  */
51 #define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
52         struct class_device_attribute class_device_attr_##_prefix##_##_name = \
53         __ATTR(_name,_mode,_show,_store)
54
55
56 /*
57  * Pretty printing helpers
58  */
59
60 #define sas_bitfield_name_match(title, table)                   \
61 static ssize_t                                                  \
62 get_sas_##title##_names(u32 table_key, char *buf)               \
63 {                                                               \
64         char *prefix = "";                                      \
65         ssize_t len = 0;                                        \
66         int i;                                                  \
67                                                                 \
68         for (i = 0; i < ARRAY_SIZE(table); i++) {               \
69                 if (table[i].value & table_key) {               \
70                         len += sprintf(buf + len, "%s%s",       \
71                                 prefix, table[i].name);         \
72                         prefix = ", ";                          \
73                 }                                               \
74         }                                                       \
75         len += sprintf(buf + len, "\n");                        \
76         return len;                                             \
77 }
78
79 #define sas_bitfield_name_search(title, table)                  \
80 static ssize_t                                                  \
81 get_sas_##title##_names(u32 table_key, char *buf)               \
82 {                                                               \
83         ssize_t len = 0;                                        \
84         int i;                                                  \
85                                                                 \
86         for (i = 0; i < ARRAY_SIZE(table); i++) {               \
87                 if (table[i].value == table_key) {              \
88                         len += sprintf(buf + len, "%s",         \
89                                 table[i].name);                 \
90                         break;                                  \
91                 }                                               \
92         }                                                       \
93         len += sprintf(buf + len, "\n");                        \
94         return len;                                             \
95 }
96
97 static struct {
98         u32             value;
99         char            *name;
100 } sas_device_type_names[] = {
101         { SAS_PHY_UNUSED,               "unused" },
102         { SAS_END_DEVICE,               "end device" },
103         { SAS_EDGE_EXPANDER_DEVICE,     "edge expander" },
104         { SAS_FANOUT_EXPANDER_DEVICE,   "fanout expander" },
105 };
106 sas_bitfield_name_search(device_type, sas_device_type_names)
107
108
109 static struct {
110         u32             value;
111         char            *name;
112 } sas_protocol_names[] = {
113         { SAS_PROTOCOL_SATA,            "sata" },
114         { SAS_PROTOCOL_SMP,             "smp" },
115         { SAS_PROTOCOL_STP,             "stp" },
116         { SAS_PROTOCOL_SSP,             "ssp" },
117 };
118 sas_bitfield_name_match(protocol, sas_protocol_names)
119
120 static struct {
121         u32             value;
122         char            *name;
123 } sas_linkspeed_names[] = {
124         { SAS_LINK_RATE_UNKNOWN,        "Unknown" },
125         { SAS_PHY_DISABLED,             "Phy disabled" },
126         { SAS_LINK_RATE_FAILED,         "Link Rate failed" },
127         { SAS_SATA_SPINUP_HOLD,         "Spin-up hold" },
128         { SAS_LINK_RATE_1_5_GBPS,       "1.5 Gbit" },
129         { SAS_LINK_RATE_3_0_GBPS,       "3.0 Gbit" },
130         { SAS_LINK_RATE_6_0_GBPS,       "6.0 Gbit" },
131 };
132 sas_bitfield_name_search(linkspeed, sas_linkspeed_names)
133
134
135 /*
136  * SAS host attributes
137  */
138
139 static int sas_host_setup(struct transport_container *tc, struct device *dev,
140                           struct class_device *cdev)
141 {
142         struct Scsi_Host *shost = dev_to_shost(dev);
143         struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
144
145         INIT_LIST_HEAD(&sas_host->rphy_list);
146         mutex_init(&sas_host->lock);
147         sas_host->next_target_id = 0;
148         sas_host->next_expander_id = 0;
149         return 0;
150 }
151
152 static DECLARE_TRANSPORT_CLASS(sas_host_class,
153                 "sas_host", sas_host_setup, NULL, NULL);
154
155 static int sas_host_match(struct attribute_container *cont,
156                             struct device *dev)
157 {
158         struct Scsi_Host *shost;
159         struct sas_internal *i;
160
161         if (!scsi_is_host_device(dev))
162                 return 0;
163         shost = dev_to_shost(dev);
164
165         if (!shost->transportt)
166                 return 0;
167         if (shost->transportt->host_attrs.ac.class !=
168                         &sas_host_class.class)
169                 return 0;
170
171         i = to_sas_internal(shost->transportt);
172         return &i->t.host_attrs.ac == cont;
173 }
174
175 static int do_sas_phy_delete(struct device *dev, void *data)
176 {
177         int pass = (int)(unsigned long)data;
178
179         if (pass == 0 && scsi_is_sas_port(dev))
180                 sas_port_delete(dev_to_sas_port(dev));
181         else if (pass == 1 && scsi_is_sas_phy(dev))
182                 sas_phy_delete(dev_to_phy(dev));
183         return 0;
184 }
185
186 /**
187  * sas_remove_children  --  tear down a devices SAS data structures
188  * @dev:        device belonging to the sas object
189  *
190  * Removes all SAS PHYs and remote PHYs for a given object
191  */
192 void sas_remove_children(struct device *dev)
193 {
194         device_for_each_child(dev, (void *)0, do_sas_phy_delete);
195         device_for_each_child(dev, (void *)1, do_sas_phy_delete);
196 }
197 EXPORT_SYMBOL(sas_remove_children);
198
199 /**
200  * sas_remove_host  --  tear down a Scsi_Host's SAS data structures
201  * @shost:      Scsi Host that is torn down
202  *
203  * Removes all SAS PHYs and remote PHYs for a given Scsi_Host.
204  * Must be called just before scsi_remove_host for SAS HBAs.
205  */
206 void sas_remove_host(struct Scsi_Host *shost)
207 {
208         sas_remove_children(&shost->shost_gendev);
209 }
210 EXPORT_SYMBOL(sas_remove_host);
211
212
213 /*
214  * SAS Phy attributes
215  */
216
217 #define sas_phy_show_simple(field, name, format_string, cast)           \
218 static ssize_t                                                          \
219 show_sas_phy_##name(struct class_device *cdev, char *buf)               \
220 {                                                                       \
221         struct sas_phy *phy = transport_class_to_phy(cdev);             \
222                                                                         \
223         return snprintf(buf, 20, format_string, cast phy->field);       \
224 }
225
226 #define sas_phy_simple_attr(field, name, format_string, type)           \
227         sas_phy_show_simple(field, name, format_string, (type)) \
228 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
229
230 #define sas_phy_show_protocol(field, name)                              \
231 static ssize_t                                                          \
232 show_sas_phy_##name(struct class_device *cdev, char *buf)               \
233 {                                                                       \
234         struct sas_phy *phy = transport_class_to_phy(cdev);             \
235                                                                         \
236         if (!phy->field)                                                \
237                 return snprintf(buf, 20, "none\n");                     \
238         return get_sas_protocol_names(phy->field, buf);         \
239 }
240
241 #define sas_phy_protocol_attr(field, name)                              \
242         sas_phy_show_protocol(field, name)                              \
243 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)
244
245 #define sas_phy_show_linkspeed(field)                                   \
246 static ssize_t                                                          \
247 show_sas_phy_##field(struct class_device *cdev, char *buf)              \
248 {                                                                       \
249         struct sas_phy *phy = transport_class_to_phy(cdev);             \
250                                                                         \
251         return get_sas_linkspeed_names(phy->field, buf);                \
252 }
253
254 #define sas_phy_linkspeed_attr(field)                                   \
255         sas_phy_show_linkspeed(field)                                   \
256 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
257
258 #define sas_phy_show_linkerror(field)                                   \
259 static ssize_t                                                          \
260 show_sas_phy_##field(struct class_device *cdev, char *buf)              \
261 {                                                                       \
262         struct sas_phy *phy = transport_class_to_phy(cdev);             \
263         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);        \
264         struct sas_internal *i = to_sas_internal(shost->transportt);    \
265         int error;                                                      \
266                                                                         \
267         if (!phy->local_attached)                                       \
268                 return -EINVAL;                                         \
269                                                                         \
270         error = i->f->get_linkerrors ? i->f->get_linkerrors(phy) : 0;   \
271         if (error)                                                      \
272                 return error;                                           \
273         return snprintf(buf, 20, "%u\n", phy->field);                   \
274 }
275
276 #define sas_phy_linkerror_attr(field)                                   \
277         sas_phy_show_linkerror(field)                                   \
278 static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)
279
280
281 static ssize_t
282 show_sas_device_type(struct class_device *cdev, char *buf)
283 {
284         struct sas_phy *phy = transport_class_to_phy(cdev);
285
286         if (!phy->identify.device_type)
287                 return snprintf(buf, 20, "none\n");
288         return get_sas_device_type_names(phy->identify.device_type, buf);
289 }
290 static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);
291
292 static ssize_t do_sas_phy_reset(struct class_device *cdev,
293                 size_t count, int hard_reset)
294 {
295         struct sas_phy *phy = transport_class_to_phy(cdev);
296         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
297         struct sas_internal *i = to_sas_internal(shost->transportt);
298         int error;
299
300         if (!phy->local_attached)
301                 return -EINVAL;
302
303         error = i->f->phy_reset(phy, hard_reset);
304         if (error)
305                 return error;
306         return count;
307 };
308
309 static ssize_t store_sas_link_reset(struct class_device *cdev,
310                 const char *buf, size_t count)
311 {
312         return do_sas_phy_reset(cdev, count, 0);
313 }
314 static CLASS_DEVICE_ATTR(link_reset, S_IWUSR, NULL, store_sas_link_reset);
315
316 static ssize_t store_sas_hard_reset(struct class_device *cdev,
317                 const char *buf, size_t count)
318 {
319         return do_sas_phy_reset(cdev, count, 1);
320 }
321 static CLASS_DEVICE_ATTR(hard_reset, S_IWUSR, NULL, store_sas_hard_reset);
322
323 sas_phy_protocol_attr(identify.initiator_port_protocols,
324                 initiator_port_protocols);
325 sas_phy_protocol_attr(identify.target_port_protocols,
326                 target_port_protocols);
327 sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
328                 unsigned long long);
329 sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
330 //sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);
331 sas_phy_linkspeed_attr(negotiated_linkrate);
332 sas_phy_linkspeed_attr(minimum_linkrate_hw);
333 sas_phy_linkspeed_attr(minimum_linkrate);
334 sas_phy_linkspeed_attr(maximum_linkrate_hw);
335 sas_phy_linkspeed_attr(maximum_linkrate);
336 sas_phy_linkerror_attr(invalid_dword_count);
337 sas_phy_linkerror_attr(running_disparity_error_count);
338 sas_phy_linkerror_attr(loss_of_dword_sync_count);
339 sas_phy_linkerror_attr(phy_reset_problem_count);
340
341
342 static DECLARE_TRANSPORT_CLASS(sas_phy_class,
343                 "sas_phy", NULL, NULL, NULL);
344
345 static int sas_phy_match(struct attribute_container *cont, struct device *dev)
346 {
347         struct Scsi_Host *shost;
348         struct sas_internal *i;
349
350         if (!scsi_is_sas_phy(dev))
351                 return 0;
352         shost = dev_to_shost(dev->parent);
353
354         if (!shost->transportt)
355                 return 0;
356         if (shost->transportt->host_attrs.ac.class !=
357                         &sas_host_class.class)
358                 return 0;
359
360         i = to_sas_internal(shost->transportt);
361         return &i->phy_attr_cont.ac == cont;
362 }
363
364 static void sas_phy_release(struct device *dev)
365 {
366         struct sas_phy *phy = dev_to_phy(dev);
367
368         put_device(dev->parent);
369         kfree(phy);
370 }
371
372 /**
373  * sas_phy_alloc  --  allocates and initialize a SAS PHY structure
374  * @parent:     Parent device
375  * @number:     Phy index
376  *
377  * Allocates an SAS PHY structure.  It will be added in the device tree
378  * below the device specified by @parent, which has to be either a Scsi_Host
379  * or sas_rphy.
380  *
381  * Returns:
382  *      SAS PHY allocated or %NULL if the allocation failed.
383  */
384 struct sas_phy *sas_phy_alloc(struct device *parent, int number)
385 {
386         struct Scsi_Host *shost = dev_to_shost(parent);
387         struct sas_phy *phy;
388
389         phy = kzalloc(sizeof(*phy), GFP_KERNEL);
390         if (!phy)
391                 return NULL;
392
393         phy->number = number;
394
395         device_initialize(&phy->dev);
396         phy->dev.parent = get_device(parent);
397         phy->dev.release = sas_phy_release;
398         INIT_LIST_HEAD(&phy->port_siblings);
399         if (scsi_is_sas_expander_device(parent)) {
400                 struct sas_rphy *rphy = dev_to_rphy(parent);
401                 sprintf(phy->dev.bus_id, "phy-%d:%d:%d", shost->host_no,
402                         rphy->scsi_target_id, number);
403         } else
404                 sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number);
405
406         transport_setup_device(&phy->dev);
407
408         return phy;
409 }
410 EXPORT_SYMBOL(sas_phy_alloc);
411
412 /**
413  * sas_phy_add  --  add a SAS PHY to the device hierachy
414  * @phy:        The PHY to be added
415  *
416  * Publishes a SAS PHY to the rest of the system.
417  */
418 int sas_phy_add(struct sas_phy *phy)
419 {
420         int error;
421
422         error = device_add(&phy->dev);
423         if (!error) {
424                 transport_add_device(&phy->dev);
425                 transport_configure_device(&phy->dev);
426         }
427
428         return error;
429 }
430 EXPORT_SYMBOL(sas_phy_add);
431
432 /**
433  * sas_phy_free  --  free a SAS PHY
434  * @phy:        SAS PHY to free
435  *
436  * Frees the specified SAS PHY.
437  *
438  * Note:
439  *   This function must only be called on a PHY that has not
440  *   sucessfully been added using sas_phy_add().
441  */
442 void sas_phy_free(struct sas_phy *phy)
443 {
444         transport_destroy_device(&phy->dev);
445         put_device(&phy->dev);
446 }
447 EXPORT_SYMBOL(sas_phy_free);
448
449 /**
450  * sas_phy_delete  --  remove SAS PHY
451  * @phy:        SAS PHY to remove
452  *
453  * Removes the specified SAS PHY.  If the SAS PHY has an
454  * associated remote PHY it is removed before.
455  */
456 void
457 sas_phy_delete(struct sas_phy *phy)
458 {
459         struct device *dev = &phy->dev;
460
461         /* this happens if the phy is still part of a port when deleted */
462         BUG_ON(!list_empty(&phy->port_siblings));
463
464         transport_remove_device(dev);
465         device_del(dev);
466         transport_destroy_device(dev);
467         put_device(dev);
468 }
469 EXPORT_SYMBOL(sas_phy_delete);
470
471 /**
472  * scsi_is_sas_phy  --  check if a struct device represents a SAS PHY
473  * @dev:        device to check
474  *
475  * Returns:
476  *      %1 if the device represents a SAS PHY, %0 else
477  */
478 int scsi_is_sas_phy(const struct device *dev)
479 {
480         return dev->release == sas_phy_release;
481 }
482 EXPORT_SYMBOL(scsi_is_sas_phy);
483
484 /*
485  * SAS Port attributes
486  */
487 #define sas_port_show_simple(field, name, format_string, cast)          \
488 static ssize_t                                                          \
489 show_sas_port_##name(struct class_device *cdev, char *buf)              \
490 {                                                                       \
491         struct sas_port *port = transport_class_to_sas_port(cdev);      \
492                                                                         \
493         return snprintf(buf, 20, format_string, cast port->field);      \
494 }
495
496 #define sas_port_simple_attr(field, name, format_string, type)          \
497         sas_port_show_simple(field, name, format_string, (type))        \
498 static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_port_##name, NULL)
499
500 sas_port_simple_attr(num_phys, num_phys, "%d\n", int);
501
502 static DECLARE_TRANSPORT_CLASS(sas_port_class,
503                                "sas_port", NULL, NULL, NULL);
504
505 static int sas_port_match(struct attribute_container *cont, struct device *dev)
506 {
507         struct Scsi_Host *shost;
508         struct sas_internal *i;
509
510         if (!scsi_is_sas_port(dev))
511                 return 0;
512         shost = dev_to_shost(dev->parent);
513
514         if (!shost->transportt)
515                 return 0;
516         if (shost->transportt->host_attrs.ac.class !=
517                         &sas_host_class.class)
518                 return 0;
519
520         i = to_sas_internal(shost->transportt);
521         return &i->port_attr_cont.ac == cont;
522 }
523
524
525 static void sas_port_release(struct device *dev)
526 {
527         struct sas_port *port = dev_to_sas_port(dev);
528
529         BUG_ON(!list_empty(&port->phy_list));
530
531         put_device(dev->parent);
532         kfree(port);
533 }
534
535 static void sas_port_create_link(struct sas_port *port,
536                                  struct sas_phy *phy)
537 {
538         sysfs_create_link(&port->dev.kobj, &phy->dev.kobj, phy->dev.bus_id);
539         sysfs_create_link(&phy->dev.kobj, &port->dev.kobj, "port");
540 }
541
542 static void sas_port_delete_link(struct sas_port *port,
543                                  struct sas_phy *phy)
544 {
545         sysfs_remove_link(&port->dev.kobj, phy->dev.bus_id);
546         sysfs_remove_link(&phy->dev.kobj, "port");
547 }
548
549 /** sas_port_alloc - allocate and initialize a SAS port structure
550  *
551  * @parent:     parent device
552  * @port_id:    port number
553  *
554  * Allocates a SAS port structure.  It will be added to the device tree
555  * below the device specified by @parent which must be either a Scsi_Host
556  * or a sas_expander_device.
557  *
558  * Returns %NULL on error
559  */
560 struct sas_port *sas_port_alloc(struct device *parent, int port_id)
561 {
562         struct Scsi_Host *shost = dev_to_shost(parent);
563         struct sas_port *port;
564
565         port = kzalloc(sizeof(*port), GFP_KERNEL);
566         if (!port)
567                 return NULL;
568
569         port->port_identifier = port_id;
570
571         device_initialize(&port->dev);
572
573         port->dev.parent = get_device(parent);
574         port->dev.release = sas_port_release;
575
576         mutex_init(&port->phy_list_mutex);
577         INIT_LIST_HEAD(&port->phy_list);
578
579         if (scsi_is_sas_expander_device(parent)) {
580                 struct sas_rphy *rphy = dev_to_rphy(parent);
581                 sprintf(port->dev.bus_id, "port-%d:%d:%d", shost->host_no,
582                         rphy->scsi_target_id, port->port_identifier);
583         } else
584                 sprintf(port->dev.bus_id, "port-%d:%d", shost->host_no,
585                         port->port_identifier);
586
587         transport_setup_device(&port->dev);
588
589         return port;
590 }
591 EXPORT_SYMBOL(sas_port_alloc);
592
593 /**
594  * sas_port_add - add a SAS port to the device hierarchy
595  *
596  * @port:       port to be added
597  *
598  * publishes a port to the rest of the system
599  */
600 int sas_port_add(struct sas_port *port)
601 {
602         int error;
603
604         /* No phys should be added until this is made visible */
605         BUG_ON(!list_empty(&port->phy_list));
606
607         error = device_add(&port->dev);
608
609         if (error)
610                 return error;
611
612         transport_add_device(&port->dev);
613         transport_configure_device(&port->dev);
614
615         return 0;
616 }
617 EXPORT_SYMBOL(sas_port_add);
618
619 /**
620  * sas_port_free  --  free a SAS PORT
621  * @port:       SAS PORT to free
622  *
623  * Frees the specified SAS PORT.
624  *
625  * Note:
626  *   This function must only be called on a PORT that has not
627  *   sucessfully been added using sas_port_add().
628  */
629 void sas_port_free(struct sas_port *port)
630 {
631         transport_destroy_device(&port->dev);
632         put_device(&port->dev);
633 }
634 EXPORT_SYMBOL(sas_port_free);
635
636 /**
637  * sas_port_delete  --  remove SAS PORT
638  * @port:       SAS PORT to remove
639  *
640  * Removes the specified SAS PORT.  If the SAS PORT has an
641  * associated phys, unlink them from the port as well.
642  */
643 void sas_port_delete(struct sas_port *port)
644 {
645         struct device *dev = &port->dev;
646         struct sas_phy *phy, *tmp_phy;
647
648         if (port->rphy) {
649                 sas_rphy_delete(port->rphy);
650                 port->rphy = NULL;
651         }
652
653         mutex_lock(&port->phy_list_mutex);
654         list_for_each_entry_safe(phy, tmp_phy, &port->phy_list,
655                                  port_siblings) {
656                 sas_port_delete_link(port, phy);
657                 list_del_init(&phy->port_siblings);
658         }
659         mutex_unlock(&port->phy_list_mutex);
660
661         transport_remove_device(dev);
662         device_del(dev);
663         transport_destroy_device(dev);
664         put_device(dev);
665 }
666 EXPORT_SYMBOL(sas_port_delete);
667
668 /**
669  * scsi_is_sas_port --  check if a struct device represents a SAS port
670  * @dev:        device to check
671  *
672  * Returns:
673  *      %1 if the device represents a SAS Port, %0 else
674  */
675 int scsi_is_sas_port(const struct device *dev)
676 {
677         return dev->release == sas_port_release;
678 }
679 EXPORT_SYMBOL(scsi_is_sas_port);
680
681 /**
682  * sas_port_add_phy - add another phy to a port to form a wide port
683  * @port:       port to add the phy to
684  * @phy:        phy to add
685  *
686  * When a port is initially created, it is empty (has no phys).  All
687  * ports must have at least one phy to operated, and all wide ports
688  * must have at least two.  The current code makes no difference
689  * between ports and wide ports, but the only object that can be
690  * connected to a remote device is a port, so ports must be formed on
691  * all devices with phys if they're connected to anything.
692  */
693 void sas_port_add_phy(struct sas_port *port, struct sas_phy *phy)
694 {
695         mutex_lock(&port->phy_list_mutex);
696         if (unlikely(!list_empty(&phy->port_siblings))) {
697                 /* make sure we're already on this port */
698                 struct sas_phy *tmp;
699
700                 list_for_each_entry(tmp, &port->phy_list, port_siblings)
701                         if (tmp == phy)
702                                 break;
703                 /* If this trips, you added a phy that was already
704                  * part of a different port */
705                 if (unlikely(tmp != phy)) {
706                         dev_printk(KERN_ERR, &port->dev, "trying to add phy %s fails: it's already part of another port\n", phy->dev.bus_id);
707                         BUG();
708                 }
709         } else {
710                 sas_port_create_link(port, phy);
711                 list_add_tail(&phy->port_siblings, &port->phy_list);
712                 port->num_phys++;
713         }
714         mutex_unlock(&port->phy_list_mutex);
715 }
716 EXPORT_SYMBOL(sas_port_add_phy);
717
718 /**
719  * sas_port_delete_phy - remove a phy from a port or wide port
720  * @port:       port to remove the phy from
721  * @phy:        phy to remove
722  *
723  * This operation is used for tearing down ports again.  It must be
724  * done to every port or wide port before calling sas_port_delete.
725  */
726 void sas_port_delete_phy(struct sas_port *port, struct sas_phy *phy)
727 {
728         mutex_lock(&port->phy_list_mutex);
729         sas_port_delete_link(port, phy);
730         list_del_init(&phy->port_siblings);
731         port->num_phys--;
732         mutex_unlock(&port->phy_list_mutex);
733 }
734 EXPORT_SYMBOL(sas_port_delete_phy);
735
736 /*
737  * SAS remote PHY attributes.
738  */
739
740 #define sas_rphy_show_simple(field, name, format_string, cast)          \
741 static ssize_t                                                          \
742 show_sas_rphy_##name(struct class_device *cdev, char *buf)              \
743 {                                                                       \
744         struct sas_rphy *rphy = transport_class_to_rphy(cdev);  \
745                                                                         \
746         return snprintf(buf, 20, format_string, cast rphy->field);      \
747 }
748
749 #define sas_rphy_simple_attr(field, name, format_string, type)          \
750         sas_rphy_show_simple(field, name, format_string, (type))        \
751 static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO,                       \
752                 show_sas_rphy_##name, NULL)
753
754 #define sas_rphy_show_protocol(field, name)                             \
755 static ssize_t                                                          \
756 show_sas_rphy_##name(struct class_device *cdev, char *buf)              \
757 {                                                                       \
758         struct sas_rphy *rphy = transport_class_to_rphy(cdev);  \
759                                                                         \
760         if (!rphy->field)                                       \
761                 return snprintf(buf, 20, "none\n");                     \
762         return get_sas_protocol_names(rphy->field, buf);        \
763 }
764
765 #define sas_rphy_protocol_attr(field, name)                             \
766         sas_rphy_show_protocol(field, name)                             \
767 static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO,                       \
768                 show_sas_rphy_##name, NULL)
769
770 static ssize_t
771 show_sas_rphy_device_type(struct class_device *cdev, char *buf)
772 {
773         struct sas_rphy *rphy = transport_class_to_rphy(cdev);
774
775         if (!rphy->identify.device_type)
776                 return snprintf(buf, 20, "none\n");
777         return get_sas_device_type_names(
778                         rphy->identify.device_type, buf);
779 }
780
781 static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO,
782                 show_sas_rphy_device_type, NULL);
783
784 static ssize_t
785 show_sas_rphy_enclosure_identifier(struct class_device *cdev, char *buf)
786 {
787         struct sas_rphy *rphy = transport_class_to_rphy(cdev);
788         struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
789         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
790         struct sas_internal *i = to_sas_internal(shost->transportt);
791         u64 identifier;
792         int error;
793
794         /*
795          * Only devices behind an expander are supported, because the
796          * enclosure identifier is a SMP feature.
797          */
798         if (phy->local_attached)
799                 return -EINVAL;
800
801         error = i->f->get_enclosure_identifier(rphy, &identifier);
802         if (error)
803                 return error;
804         return sprintf(buf, "0x%llx\n", (unsigned long long)identifier);
805 }
806
807 static SAS_CLASS_DEVICE_ATTR(rphy, enclosure_identifier, S_IRUGO,
808                 show_sas_rphy_enclosure_identifier, NULL);
809
810 static ssize_t
811 show_sas_rphy_bay_identifier(struct class_device *cdev, char *buf)
812 {
813         struct sas_rphy *rphy = transport_class_to_rphy(cdev);
814         struct sas_phy *phy = dev_to_phy(rphy->dev.parent);
815         struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
816         struct sas_internal *i = to_sas_internal(shost->transportt);
817         int val;
818
819         if (phy->local_attached)
820                 return -EINVAL;
821
822         val = i->f->get_bay_identifier(rphy);
823         if (val < 0)
824                 return val;
825         return sprintf(buf, "%d\n", val);
826 }
827
828 static SAS_CLASS_DEVICE_ATTR(rphy, bay_identifier, S_IRUGO,
829                 show_sas_rphy_bay_identifier, NULL);
830
831 sas_rphy_protocol_attr(identify.initiator_port_protocols,
832                 initiator_port_protocols);
833 sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols);
834 sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",
835                 unsigned long long);
836 sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);
837
838 /* only need 8 bytes of data plus header (4 or 8) */
839 #define BUF_SIZE 64
840
841 int sas_read_port_mode_page(struct scsi_device *sdev)
842 {
843         char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata;
844         struct sas_rphy *rphy = target_to_rphy(sdev->sdev_target);
845         struct sas_end_device *rdev;
846         struct scsi_mode_data mode_data;
847         int res, error;
848
849         BUG_ON(rphy->identify.device_type != SAS_END_DEVICE);
850
851         rdev = rphy_to_end_device(rphy);
852
853         if (!buffer)
854                 return -ENOMEM;
855
856         res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3,
857                               &mode_data, NULL);
858
859         error = -EINVAL;
860         if (!scsi_status_is_good(res))
861                 goto out;
862
863         msdata = buffer +  mode_data.header_length +
864                 mode_data.block_descriptor_length;
865
866         if (msdata - buffer > BUF_SIZE - 8)
867                 goto out;
868
869         error = 0;
870
871         rdev->ready_led_meaning = msdata[2] & 0x10 ? 1 : 0;
872         rdev->I_T_nexus_loss_timeout = (msdata[4] << 8) + msdata[5];
873         rdev->initiator_response_timeout = (msdata[6] << 8) + msdata[7];
874
875  out:
876         kfree(buffer);
877         return error;
878 }
879 EXPORT_SYMBOL(sas_read_port_mode_page);
880
881 static DECLARE_TRANSPORT_CLASS(sas_end_dev_class,
882                                "sas_end_device", NULL, NULL, NULL);
883
884 #define sas_end_dev_show_simple(field, name, format_string, cast)       \
885 static ssize_t                                                          \
886 show_sas_end_dev_##name(struct class_device *cdev, char *buf)           \
887 {                                                                       \
888         struct sas_rphy *rphy = transport_class_to_rphy(cdev);          \
889         struct sas_end_device *rdev = rphy_to_end_device(rphy);         \
890                                                                         \
891         return snprintf(buf, 20, format_string, cast rdev->field);      \
892 }
893
894 #define sas_end_dev_simple_attr(field, name, format_string, type)       \
895         sas_end_dev_show_simple(field, name, format_string, (type))     \
896 static SAS_CLASS_DEVICE_ATTR(end_dev, name, S_IRUGO,                    \
897                 show_sas_end_dev_##name, NULL)
898
899 sas_end_dev_simple_attr(ready_led_meaning, ready_led_meaning, "%d\n", int);
900 sas_end_dev_simple_attr(I_T_nexus_loss_timeout, I_T_nexus_loss_timeout,
901                         "%d\n", int);
902 sas_end_dev_simple_attr(initiator_response_timeout, initiator_response_timeout,
903                         "%d\n", int);
904
905 static DECLARE_TRANSPORT_CLASS(sas_expander_class,
906                                "sas_expander", NULL, NULL, NULL);
907
908 #define sas_expander_show_simple(field, name, format_string, cast)      \
909 static ssize_t                                                          \
910 show_sas_expander_##name(struct class_device *cdev, char *buf)          \
911 {                                                                       \
912         struct sas_rphy *rphy = transport_class_to_rphy(cdev);          \
913         struct sas_expander_device *edev = rphy_to_expander_device(rphy); \
914                                                                         \
915         return snprintf(buf, 20, format_string, cast edev->field);      \
916 }
917
918 #define sas_expander_simple_attr(field, name, format_string, type)      \
919         sas_expander_show_simple(field, name, format_string, (type))    \
920 static SAS_CLASS_DEVICE_ATTR(expander, name, S_IRUGO,                   \
921                 show_sas_expander_##name, NULL)
922
923 sas_expander_simple_attr(vendor_id, vendor_id, "%s\n", char *);
924 sas_expander_simple_attr(product_id, product_id, "%s\n", char *);
925 sas_expander_simple_attr(product_rev, product_rev, "%s\n", char *);
926 sas_expander_simple_attr(component_vendor_id, component_vendor_id,
927                          "%s\n", char *);
928 sas_expander_simple_attr(component_id, component_id, "%u\n", unsigned int);
929 sas_expander_simple_attr(component_revision_id, component_revision_id, "%u\n",
930                          unsigned int);
931 sas_expander_simple_attr(level, level, "%d\n", int);
932
933 static DECLARE_TRANSPORT_CLASS(sas_rphy_class,
934                 "sas_device", NULL, NULL, NULL);
935
936 static int sas_rphy_match(struct attribute_container *cont, struct device *dev)
937 {
938         struct Scsi_Host *shost;
939         struct sas_internal *i;
940
941         if (!scsi_is_sas_rphy(dev))
942                 return 0;
943         shost = dev_to_shost(dev->parent->parent);
944
945         if (!shost->transportt)
946                 return 0;
947         if (shost->transportt->host_attrs.ac.class !=
948                         &sas_host_class.class)
949                 return 0;
950
951         i = to_sas_internal(shost->transportt);
952         return &i->rphy_attr_cont.ac == cont;
953 }
954
955 static int sas_end_dev_match(struct attribute_container *cont,
956                              struct device *dev)
957 {
958         struct Scsi_Host *shost;
959         struct sas_internal *i;
960         struct sas_rphy *rphy;
961
962         if (!scsi_is_sas_rphy(dev))
963                 return 0;
964         shost = dev_to_shost(dev->parent->parent);
965         rphy = dev_to_rphy(dev);
966
967         if (!shost->transportt)
968                 return 0;
969         if (shost->transportt->host_attrs.ac.class !=
970                         &sas_host_class.class)
971                 return 0;
972
973         i = to_sas_internal(shost->transportt);
974         return &i->end_dev_attr_cont.ac == cont &&
975                 rphy->identify.device_type == SAS_END_DEVICE;
976 }
977
978 static int sas_expander_match(struct attribute_container *cont,
979                               struct device *dev)
980 {
981         struct Scsi_Host *shost;
982         struct sas_internal *i;
983         struct sas_rphy *rphy;
984
985         if (!scsi_is_sas_rphy(dev))
986                 return 0;
987         shost = dev_to_shost(dev->parent->parent);
988         rphy = dev_to_rphy(dev);
989
990         if (!shost->transportt)
991                 return 0;
992         if (shost->transportt->host_attrs.ac.class !=
993                         &sas_host_class.class)
994                 return 0;
995
996         i = to_sas_internal(shost->transportt);
997         return &i->expander_attr_cont.ac == cont &&
998                 (rphy->identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
999                  rphy->identify.device_type == SAS_FANOUT_EXPANDER_DEVICE);
1000 }
1001
1002 static void sas_expander_release(struct device *dev)
1003 {
1004         struct sas_rphy *rphy = dev_to_rphy(dev);
1005         struct sas_expander_device *edev = rphy_to_expander_device(rphy);
1006
1007         put_device(dev->parent);
1008         kfree(edev);
1009 }
1010
1011 static void sas_end_device_release(struct device *dev)
1012 {
1013         struct sas_rphy *rphy = dev_to_rphy(dev);
1014         struct sas_end_device *edev = rphy_to_end_device(rphy);
1015
1016         put_device(dev->parent);
1017         kfree(edev);
1018 }
1019
1020 /**
1021  * sas_rphy_initialize - common rphy intialization
1022  * @rphy:       rphy to initialise
1023  *
1024  * Used by both sas_end_device_alloc() and sas_expander_alloc() to
1025  * initialise the common rphy component of each.
1026  */
1027 static void sas_rphy_initialize(struct sas_rphy *rphy)
1028 {
1029         INIT_LIST_HEAD(&rphy->list);
1030 }
1031
1032 /**
1033  * sas_end_device_alloc - allocate an rphy for an end device
1034  *
1035  * Allocates an SAS remote PHY structure, connected to @parent.
1036  *
1037  * Returns:
1038  *      SAS PHY allocated or %NULL if the allocation failed.
1039  */
1040 struct sas_rphy *sas_end_device_alloc(struct sas_port *parent)
1041 {
1042         struct Scsi_Host *shost = dev_to_shost(&parent->dev);
1043         struct sas_end_device *rdev;
1044
1045         rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
1046         if (!rdev) {
1047                 return NULL;
1048         }
1049
1050         device_initialize(&rdev->rphy.dev);
1051         rdev->rphy.dev.parent = get_device(&parent->dev);
1052         rdev->rphy.dev.release = sas_end_device_release;
1053         if (scsi_is_sas_expander_device(parent->dev.parent)) {
1054                 struct sas_rphy *rphy = dev_to_rphy(parent->dev.parent);
1055                 sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d:%d",
1056                         shost->host_no, rphy->scsi_target_id, parent->port_identifier);
1057         } else
1058                 sprintf(rdev->rphy.dev.bus_id, "end_device-%d:%d",
1059                         shost->host_no, parent->port_identifier);
1060         rdev->rphy.identify.device_type = SAS_END_DEVICE;
1061         sas_rphy_initialize(&rdev->rphy);
1062         transport_setup_device(&rdev->rphy.dev);
1063
1064         return &rdev->rphy;
1065 }
1066 EXPORT_SYMBOL(sas_end_device_alloc);
1067
1068 /**
1069  * sas_expander_alloc - allocate an rphy for an end device
1070  *
1071  * Allocates an SAS remote PHY structure, connected to @parent.
1072  *
1073  * Returns:
1074  *      SAS PHY allocated or %NULL if the allocation failed.
1075  */
1076 struct sas_rphy *sas_expander_alloc(struct sas_port *parent,
1077                                     enum sas_device_type type)
1078 {
1079         struct Scsi_Host *shost = dev_to_shost(&parent->dev);
1080         struct sas_expander_device *rdev;
1081         struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1082
1083         BUG_ON(type != SAS_EDGE_EXPANDER_DEVICE &&
1084                type != SAS_FANOUT_EXPANDER_DEVICE);
1085
1086         rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
1087         if (!rdev) {
1088                 return NULL;
1089         }
1090
1091         device_initialize(&rdev->rphy.dev);
1092         rdev->rphy.dev.parent = get_device(&parent->dev);
1093         rdev->rphy.dev.release = sas_expander_release;
1094         mutex_lock(&sas_host->lock);
1095         rdev->rphy.scsi_target_id = sas_host->next_expander_id++;
1096         mutex_unlock(&sas_host->lock);
1097         sprintf(rdev->rphy.dev.bus_id, "expander-%d:%d",
1098                 shost->host_no, rdev->rphy.scsi_target_id);
1099         rdev->rphy.identify.device_type = type;
1100         sas_rphy_initialize(&rdev->rphy);
1101         transport_setup_device(&rdev->rphy.dev);
1102
1103         return &rdev->rphy;
1104 }
1105 EXPORT_SYMBOL(sas_expander_alloc);
1106
1107 /**
1108  * sas_rphy_add  --  add a SAS remote PHY to the device hierachy
1109  * @rphy:       The remote PHY to be added
1110  *
1111  * Publishes a SAS remote PHY to the rest of the system.
1112  */
1113 int sas_rphy_add(struct sas_rphy *rphy)
1114 {
1115         struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
1116         struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
1117         struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1118         struct sas_identify *identify = &rphy->identify;
1119         int error;
1120
1121         if (parent->rphy)
1122                 return -ENXIO;
1123         parent->rphy = rphy;
1124
1125         error = device_add(&rphy->dev);
1126         if (error)
1127                 return error;
1128         transport_add_device(&rphy->dev);
1129         transport_configure_device(&rphy->dev);
1130
1131         mutex_lock(&sas_host->lock);
1132         list_add_tail(&rphy->list, &sas_host->rphy_list);
1133         if (identify->device_type == SAS_END_DEVICE &&
1134             (identify->target_port_protocols &
1135              (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))
1136                 rphy->scsi_target_id = sas_host->next_target_id++;
1137         else if (identify->device_type == SAS_END_DEVICE)
1138                 rphy->scsi_target_id = -1;
1139         mutex_unlock(&sas_host->lock);
1140
1141         if (identify->device_type == SAS_END_DEVICE &&
1142             rphy->scsi_target_id != -1) {
1143                 scsi_scan_target(&rphy->dev, parent->port_identifier,
1144                                 rphy->scsi_target_id, ~0, 0);
1145         }
1146
1147         return 0;
1148 }
1149 EXPORT_SYMBOL(sas_rphy_add);
1150
1151 /**
1152  * sas_rphy_free  --  free a SAS remote PHY
1153  * @rphy        SAS remote PHY to free
1154  *
1155  * Frees the specified SAS remote PHY.
1156  *
1157  * Note:
1158  *   This function must only be called on a remote
1159  *   PHY that has not sucessfully been added using
1160  *   sas_rphy_add().
1161  */
1162 void sas_rphy_free(struct sas_rphy *rphy)
1163 {
1164         struct device *dev = &rphy->dev;
1165         struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
1166         struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1167
1168         mutex_lock(&sas_host->lock);
1169         list_del(&rphy->list);
1170         mutex_unlock(&sas_host->lock);
1171
1172         transport_destroy_device(dev);
1173
1174         put_device(dev);
1175 }
1176 EXPORT_SYMBOL(sas_rphy_free);
1177
1178 /**
1179  * sas_rphy_delete  --  remove SAS remote PHY
1180  * @rphy:       SAS remote PHY to remove
1181  *
1182  * Removes the specified SAS remote PHY.
1183  */
1184 void
1185 sas_rphy_delete(struct sas_rphy *rphy)
1186 {
1187         struct device *dev = &rphy->dev;
1188         struct sas_port *parent = dev_to_sas_port(dev->parent);
1189         struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);
1190         struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1191
1192         switch (rphy->identify.device_type) {
1193         case SAS_END_DEVICE:
1194                 scsi_remove_target(dev);
1195                 break;
1196         case SAS_EDGE_EXPANDER_DEVICE:
1197         case SAS_FANOUT_EXPANDER_DEVICE:
1198                 sas_remove_children(dev);
1199                 break;
1200         default:
1201                 break;
1202         }
1203
1204         transport_remove_device(dev);
1205         device_del(dev);
1206         transport_destroy_device(dev);
1207
1208         mutex_lock(&sas_host->lock);
1209         list_del(&rphy->list);
1210         mutex_unlock(&sas_host->lock);
1211
1212         parent->rphy = NULL;
1213
1214         put_device(dev);
1215 }
1216 EXPORT_SYMBOL(sas_rphy_delete);
1217
1218 /**
1219  * scsi_is_sas_rphy  --  check if a struct device represents a SAS remote PHY
1220  * @dev:        device to check
1221  *
1222  * Returns:
1223  *      %1 if the device represents a SAS remote PHY, %0 else
1224  */
1225 int scsi_is_sas_rphy(const struct device *dev)
1226 {
1227         return dev->release == sas_end_device_release ||
1228                 dev->release == sas_expander_release;
1229 }
1230 EXPORT_SYMBOL(scsi_is_sas_rphy);
1231
1232
1233 /*
1234  * SCSI scan helper
1235  */
1236
1237 static int sas_user_scan(struct Scsi_Host *shost, uint channel,
1238                 uint id, uint lun)
1239 {
1240         struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);
1241         struct sas_rphy *rphy;
1242
1243         mutex_lock(&sas_host->lock);
1244         list_for_each_entry(rphy, &sas_host->rphy_list, list) {
1245                 struct sas_port *parent = dev_to_sas_port(rphy->dev.parent);
1246
1247                 if (rphy->identify.device_type != SAS_END_DEVICE ||
1248                     rphy->scsi_target_id == -1)
1249                         continue;
1250
1251                 if ((channel == SCAN_WILD_CARD || channel == parent->port_identifier) &&
1252                     (id == SCAN_WILD_CARD || id == rphy->scsi_target_id)) {
1253                         scsi_scan_target(&rphy->dev, parent->port_identifier,
1254                                          rphy->scsi_target_id, lun, 1);
1255                 }
1256         }
1257         mutex_unlock(&sas_host->lock);
1258
1259         return 0;
1260 }
1261
1262
1263 /*
1264  * Setup / Teardown code
1265  */
1266
1267 #define SETUP_TEMPLATE(attrb, field, perm, test)                                \
1268         i->private_##attrb[count] = class_device_attr_##field;          \
1269         i->private_##attrb[count].attr.mode = perm;                     \
1270         i->attrb[count] = &i->private_##attrb[count];                   \
1271         if (test)                                                       \
1272                 count++
1273
1274
1275 #define SETUP_RPORT_ATTRIBUTE(field)                                    \
1276         SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, 1)
1277
1278 #define SETUP_OPTIONAL_RPORT_ATTRIBUTE(field, func)                     \
1279         SETUP_TEMPLATE(rphy_attrs, field, S_IRUGO, i->f->func)
1280
1281 #define SETUP_PHY_ATTRIBUTE(field)                                      \
1282         SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, 1)
1283
1284 #define SETUP_PORT_ATTRIBUTE(field)                                     \
1285         SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
1286
1287 #define SETUP_OPTIONAL_PHY_ATTRIBUTE(field, func)                       \
1288         SETUP_TEMPLATE(phy_attrs, field, S_IRUGO, i->f->func)
1289
1290 #define SETUP_PHY_ATTRIBUTE_WRONLY(field)                               \
1291         SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, 1)
1292
1293 #define SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(field, func)                \
1294         SETUP_TEMPLATE(phy_attrs, field, S_IWUGO, i->f->func)
1295
1296 #define SETUP_END_DEV_ATTRIBUTE(field)                                  \
1297         SETUP_TEMPLATE(end_dev_attrs, field, S_IRUGO, 1)
1298
1299 #define SETUP_EXPANDER_ATTRIBUTE(field)                                 \
1300         SETUP_TEMPLATE(expander_attrs, expander_##field, S_IRUGO, 1)
1301
1302 /**
1303  * sas_attach_transport  --  instantiate SAS transport template
1304  * @ft:         SAS transport class function template
1305  */
1306 struct scsi_transport_template *
1307 sas_attach_transport(struct sas_function_template *ft)
1308 {
1309         struct sas_internal *i;
1310         int count;
1311
1312         i = kzalloc(sizeof(struct sas_internal), GFP_KERNEL);
1313         if (!i)
1314                 return NULL;
1315
1316         i->t.user_scan = sas_user_scan;
1317
1318         i->t.host_attrs.ac.attrs = &i->host_attrs[0];
1319         i->t.host_attrs.ac.class = &sas_host_class.class;
1320         i->t.host_attrs.ac.match = sas_host_match;
1321         transport_container_register(&i->t.host_attrs);
1322         i->t.host_size = sizeof(struct sas_host_attrs);
1323
1324         i->phy_attr_cont.ac.class = &sas_phy_class.class;
1325         i->phy_attr_cont.ac.attrs = &i->phy_attrs[0];
1326         i->phy_attr_cont.ac.match = sas_phy_match;
1327         transport_container_register(&i->phy_attr_cont);
1328
1329         i->port_attr_cont.ac.class = &sas_port_class.class;
1330         i->port_attr_cont.ac.attrs = &i->port_attrs[0];
1331         i->port_attr_cont.ac.match = sas_port_match;
1332         transport_container_register(&i->port_attr_cont);
1333
1334         i->rphy_attr_cont.ac.class = &sas_rphy_class.class;
1335         i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0];
1336         i->rphy_attr_cont.ac.match = sas_rphy_match;
1337         transport_container_register(&i->rphy_attr_cont);
1338
1339         i->end_dev_attr_cont.ac.class = &sas_end_dev_class.class;
1340         i->end_dev_attr_cont.ac.attrs = &i->end_dev_attrs[0];
1341         i->end_dev_attr_cont.ac.match = sas_end_dev_match;
1342         transport_container_register(&i->end_dev_attr_cont);
1343
1344         i->expander_attr_cont.ac.class = &sas_expander_class.class;
1345         i->expander_attr_cont.ac.attrs = &i->expander_attrs[0];
1346         i->expander_attr_cont.ac.match = sas_expander_match;
1347         transport_container_register(&i->expander_attr_cont);
1348
1349         i->f = ft;
1350
1351         count = 0;
1352         SETUP_PORT_ATTRIBUTE(num_phys);
1353         i->host_attrs[count] = NULL;
1354
1355         count = 0;
1356         SETUP_PHY_ATTRIBUTE(initiator_port_protocols);
1357         SETUP_PHY_ATTRIBUTE(target_port_protocols);
1358         SETUP_PHY_ATTRIBUTE(device_type);
1359         SETUP_PHY_ATTRIBUTE(sas_address);
1360         SETUP_PHY_ATTRIBUTE(phy_identifier);
1361         //SETUP_PHY_ATTRIBUTE(port_identifier);
1362         SETUP_PHY_ATTRIBUTE(negotiated_linkrate);
1363         SETUP_PHY_ATTRIBUTE(minimum_linkrate_hw);
1364         SETUP_PHY_ATTRIBUTE(minimum_linkrate);
1365         SETUP_PHY_ATTRIBUTE(maximum_linkrate_hw);
1366         SETUP_PHY_ATTRIBUTE(maximum_linkrate);
1367
1368         SETUP_PHY_ATTRIBUTE(invalid_dword_count);
1369         SETUP_PHY_ATTRIBUTE(running_disparity_error_count);
1370         SETUP_PHY_ATTRIBUTE(loss_of_dword_sync_count);
1371         SETUP_PHY_ATTRIBUTE(phy_reset_problem_count);
1372         SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(link_reset, phy_reset);
1373         SETUP_OPTIONAL_PHY_ATTRIBUTE_WRONLY(hard_reset, phy_reset);
1374         i->phy_attrs[count] = NULL;
1375
1376         count = 0;
1377         SETUP_PORT_ATTRIBUTE(num_phys);
1378         i->port_attrs[count] = NULL;
1379
1380         count = 0;
1381         SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols);
1382         SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols);
1383         SETUP_RPORT_ATTRIBUTE(rphy_device_type);
1384         SETUP_RPORT_ATTRIBUTE(rphy_sas_address);
1385         SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier);
1386         SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_enclosure_identifier,
1387                                        get_enclosure_identifier);
1388         SETUP_OPTIONAL_RPORT_ATTRIBUTE(rphy_bay_identifier,
1389                                        get_bay_identifier);
1390         i->rphy_attrs[count] = NULL;
1391
1392         count = 0;
1393         SETUP_END_DEV_ATTRIBUTE(end_dev_ready_led_meaning);
1394         SETUP_END_DEV_ATTRIBUTE(end_dev_I_T_nexus_loss_timeout);
1395         SETUP_END_DEV_ATTRIBUTE(end_dev_initiator_response_timeout);
1396         i->end_dev_attrs[count] = NULL;
1397
1398         count = 0;
1399         SETUP_EXPANDER_ATTRIBUTE(vendor_id);
1400         SETUP_EXPANDER_ATTRIBUTE(product_id);
1401         SETUP_EXPANDER_ATTRIBUTE(product_rev);
1402         SETUP_EXPANDER_ATTRIBUTE(component_vendor_id);
1403         SETUP_EXPANDER_ATTRIBUTE(component_id);
1404         SETUP_EXPANDER_ATTRIBUTE(component_revision_id);
1405         SETUP_EXPANDER_ATTRIBUTE(level);
1406         i->expander_attrs[count] = NULL;
1407
1408         return &i->t;
1409 }
1410 EXPORT_SYMBOL(sas_attach_transport);
1411
1412 /**
1413  * sas_release_transport  --  release SAS transport template instance
1414  * @t:          transport template instance
1415  */
1416 void sas_release_transport(struct scsi_transport_template *t)
1417 {
1418         struct sas_internal *i = to_sas_internal(t);
1419
1420         transport_container_unregister(&i->t.host_attrs);
1421         transport_container_unregister(&i->phy_attr_cont);
1422         transport_container_unregister(&i->port_attr_cont);
1423         transport_container_unregister(&i->rphy_attr_cont);
1424         transport_container_unregister(&i->end_dev_attr_cont);
1425         transport_container_unregister(&i->expander_attr_cont);
1426
1427         kfree(i);
1428 }
1429 EXPORT_SYMBOL(sas_release_transport);
1430
1431 static __init int sas_transport_init(void)
1432 {
1433         int error;
1434
1435         error = transport_class_register(&sas_host_class);
1436         if (error)
1437                 goto out;
1438         error = transport_class_register(&sas_phy_class);
1439         if (error)
1440                 goto out_unregister_transport;
1441         error = transport_class_register(&sas_port_class);
1442         if (error)
1443                 goto out_unregister_phy;
1444         error = transport_class_register(&sas_rphy_class);
1445         if (error)
1446                 goto out_unregister_port;
1447         error = transport_class_register(&sas_end_dev_class);
1448         if (error)
1449                 goto out_unregister_rphy;
1450         error = transport_class_register(&sas_expander_class);
1451         if (error)
1452                 goto out_unregister_end_dev;
1453
1454         return 0;
1455
1456  out_unregister_end_dev:
1457         transport_class_unregister(&sas_end_dev_class);
1458  out_unregister_rphy:
1459         transport_class_unregister(&sas_rphy_class);
1460  out_unregister_port:
1461         transport_class_unregister(&sas_port_class);
1462  out_unregister_phy:
1463         transport_class_unregister(&sas_phy_class);
1464  out_unregister_transport:
1465         transport_class_unregister(&sas_host_class);
1466  out:
1467         return error;
1468
1469 }
1470
1471 static void __exit sas_transport_exit(void)
1472 {
1473         transport_class_unregister(&sas_host_class);
1474         transport_class_unregister(&sas_phy_class);
1475         transport_class_unregister(&sas_port_class);
1476         transport_class_unregister(&sas_rphy_class);
1477         transport_class_unregister(&sas_end_dev_class);
1478         transport_class_unregister(&sas_expander_class);
1479 }
1480
1481 MODULE_AUTHOR("Christoph Hellwig");
1482 MODULE_DESCRIPTION("SAS Transphy Attributes");
1483 MODULE_LICENSE("GPL");
1484
1485 module_init(sas_transport_init);
1486 module_exit(sas_transport_exit);