xref: /openbmc/linux/drivers/ata/libata-transport.c (revision 95289e49f0a05f729a9ff86243c9aff4f34d4041)
159bd9dedSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d9027470SGwendal Grignou /*
3d9027470SGwendal Grignou  *  Copyright 2008 ioogle, Inc.  All rights reserved.
4d9027470SGwendal Grignou  *
5d9027470SGwendal Grignou  * Libata transport class.
6d9027470SGwendal Grignou  *
7d9027470SGwendal Grignou  * The ATA transport class contains common code to deal with ATA HBAs,
8d9027470SGwendal Grignou  * an approximated representation of ATA topologies in the driver model,
9d9027470SGwendal Grignou  * and various sysfs attributes to expose these topologies and management
10d9027470SGwendal Grignou  * interfaces to user-space.
11d9027470SGwendal Grignou  *
1234a4d048SXiang wangx  * There are 3 objects defined in this class:
13d9027470SGwendal Grignou  * - ata_port
14d9027470SGwendal Grignou  * - ata_link
15d9027470SGwendal Grignou  * - ata_device
16d9027470SGwendal Grignou  * Each port has a link object. Each link can have up to two devices for PATA
17d9027470SGwendal Grignou  * and generally one for SATA.
18d9027470SGwendal Grignou  * If there is SATA port multiplier [PMP], 15 additional ata_link object are
19d9027470SGwendal Grignou  * created.
20d9027470SGwendal Grignou  *
21d9027470SGwendal Grignou  * These objects are created when the ata host is initialized and when a PMP is
22d9027470SGwendal Grignou  * found. They are removed only when the HBA is removed, cleaned before the
23d9027470SGwendal Grignou  * error handler runs.
24d9027470SGwendal Grignou  */
25d9027470SGwendal Grignou 
26d9027470SGwendal Grignou 
27d9027470SGwendal Grignou #include <linux/kernel.h>
28d9027470SGwendal Grignou #include <linux/blkdev.h>
29d9027470SGwendal Grignou #include <linux/spinlock.h>
306a2148c6SJeff Garzik #include <linux/slab.h>
31d9027470SGwendal Grignou #include <scsi/scsi_transport.h>
32d9027470SGwendal Grignou #include <linux/libata.h>
33d9027470SGwendal Grignou #include <linux/hdreg.h>
34d9027470SGwendal Grignou #include <linux/uaccess.h>
359ee4f393SLin Ming #include <linux/pm_runtime.h>
36d9027470SGwendal Grignou 
37d9027470SGwendal Grignou #include "libata.h"
38d9027470SGwendal Grignou #include "libata-transport.h"
39d9027470SGwendal Grignou 
40e628dc99SDavid Milburn #define ATA_PORT_ATTRS		3
41d9027470SGwendal Grignou #define ATA_LINK_ATTRS		3
42d9027470SGwendal Grignou #define ATA_DEV_ATTRS		9
43d9027470SGwendal Grignou 
44d9027470SGwendal Grignou struct scsi_transport_template;
45d9027470SGwendal Grignou struct scsi_transport_template *ata_scsi_transport_template;
46d9027470SGwendal Grignou 
47d9027470SGwendal Grignou struct ata_internal {
48d9027470SGwendal Grignou 	struct scsi_transport_template t;
49d9027470SGwendal Grignou 
50d9027470SGwendal Grignou 	struct device_attribute private_port_attrs[ATA_PORT_ATTRS];
51d9027470SGwendal Grignou 	struct device_attribute private_link_attrs[ATA_LINK_ATTRS];
52d9027470SGwendal Grignou 	struct device_attribute private_dev_attrs[ATA_DEV_ATTRS];
53d9027470SGwendal Grignou 
54d9027470SGwendal Grignou 	struct transport_container link_attr_cont;
55d9027470SGwendal Grignou 	struct transport_container dev_attr_cont;
56d9027470SGwendal Grignou 
57d9027470SGwendal Grignou 	/*
58d9027470SGwendal Grignou 	 * The array of null terminated pointers to attributes
59d9027470SGwendal Grignou 	 * needed by scsi_sysfs.c
60d9027470SGwendal Grignou 	 */
61d9027470SGwendal Grignou 	struct device_attribute *link_attrs[ATA_LINK_ATTRS + 1];
62d9027470SGwendal Grignou 	struct device_attribute *port_attrs[ATA_PORT_ATTRS + 1];
63d9027470SGwendal Grignou 	struct device_attribute *dev_attrs[ATA_DEV_ATTRS + 1];
64d9027470SGwendal Grignou };
65d9027470SGwendal Grignou #define to_ata_internal(tmpl)	container_of(tmpl, struct ata_internal, t)
66d9027470SGwendal Grignou 
67d9027470SGwendal Grignou 
68d9027470SGwendal Grignou #define tdev_to_device(d)					\
69d9027470SGwendal Grignou 	container_of((d), struct ata_device, tdev)
70d9027470SGwendal Grignou #define transport_class_to_dev(dev)				\
71d9027470SGwendal Grignou 	tdev_to_device((dev)->parent)
72d9027470SGwendal Grignou 
73d9027470SGwendal Grignou #define tdev_to_link(d)						\
74d9027470SGwendal Grignou 	container_of((d), struct ata_link, tdev)
75d9027470SGwendal Grignou #define transport_class_to_link(dev)				\
76d9027470SGwendal Grignou 	tdev_to_link((dev)->parent)
77d9027470SGwendal Grignou 
78d9027470SGwendal Grignou #define tdev_to_port(d)						\
79d9027470SGwendal Grignou 	container_of((d), struct ata_port, tdev)
80d9027470SGwendal Grignou #define transport_class_to_port(dev)				\
81d9027470SGwendal Grignou 	tdev_to_port((dev)->parent)
82d9027470SGwendal Grignou 
83d9027470SGwendal Grignou 
84d9027470SGwendal Grignou /* Device objects are always created whit link objects */
85d9027470SGwendal Grignou static int ata_tdev_add(struct ata_device *dev);
86d9027470SGwendal Grignou static void ata_tdev_delete(struct ata_device *dev);
87d9027470SGwendal Grignou 
88d9027470SGwendal Grignou 
89d9027470SGwendal Grignou /*
90d9027470SGwendal Grignou  * Hack to allow attributes of the same name in different objects.
91d9027470SGwendal Grignou  */
92d9027470SGwendal Grignou #define ATA_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \
93d9027470SGwendal Grignou 	struct device_attribute device_attr_##_prefix##_##_name = \
94d9027470SGwendal Grignou 	__ATTR(_name,_mode,_show,_store)
95d9027470SGwendal Grignou 
96d9027470SGwendal Grignou #define ata_bitfield_name_match(title, table)			\
97d9027470SGwendal Grignou static ssize_t							\
98d9027470SGwendal Grignou get_ata_##title##_names(u32 table_key, char *buf)		\
99d9027470SGwendal Grignou {								\
100d9027470SGwendal Grignou 	char *prefix = "";					\
101d9027470SGwendal Grignou 	ssize_t len = 0;					\
102d9027470SGwendal Grignou 	int i;							\
103d9027470SGwendal Grignou 								\
104d9027470SGwendal Grignou 	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
105d9027470SGwendal Grignou 		if (table[i].value & table_key) {		\
106d9027470SGwendal Grignou 			len += sprintf(buf + len, "%s%s",	\
107d9027470SGwendal Grignou 				prefix, table[i].name);		\
108d9027470SGwendal Grignou 			prefix = ", ";				\
109d9027470SGwendal Grignou 		}						\
110d9027470SGwendal Grignou 	}							\
111d9027470SGwendal Grignou 	len += sprintf(buf + len, "\n");			\
112d9027470SGwendal Grignou 	return len;						\
113d9027470SGwendal Grignou }
114d9027470SGwendal Grignou 
115d9027470SGwendal Grignou #define ata_bitfield_name_search(title, table)			\
116d9027470SGwendal Grignou static ssize_t							\
117d9027470SGwendal Grignou get_ata_##title##_names(u32 table_key, char *buf)		\
118d9027470SGwendal Grignou {								\
119d9027470SGwendal Grignou 	ssize_t len = 0;					\
120d9027470SGwendal Grignou 	int i;							\
121d9027470SGwendal Grignou 								\
122d9027470SGwendal Grignou 	for (i = 0; i < ARRAY_SIZE(table); i++) {		\
123d9027470SGwendal Grignou 		if (table[i].value == table_key) {		\
124d9027470SGwendal Grignou 			len += sprintf(buf + len, "%s",		\
125d9027470SGwendal Grignou 				table[i].name);			\
126d9027470SGwendal Grignou 			break;					\
127d9027470SGwendal Grignou 		}						\
128d9027470SGwendal Grignou 	}							\
129d9027470SGwendal Grignou 	len += sprintf(buf + len, "\n");			\
130d9027470SGwendal Grignou 	return len;						\
131d9027470SGwendal Grignou }
132d9027470SGwendal Grignou 
133d9027470SGwendal Grignou static struct {
134d9027470SGwendal Grignou 	u32		value;
135d9027470SGwendal Grignou 	char		*name;
136d9027470SGwendal Grignou } ata_class_names[] = {
137d9027470SGwendal Grignou 	{ ATA_DEV_UNKNOWN,		"unknown" },
138d9027470SGwendal Grignou 	{ ATA_DEV_ATA,			"ata" },
139d9027470SGwendal Grignou 	{ ATA_DEV_ATA_UNSUP,		"ata" },
140d9027470SGwendal Grignou 	{ ATA_DEV_ATAPI,		"atapi" },
141d9027470SGwendal Grignou 	{ ATA_DEV_ATAPI_UNSUP,		"atapi" },
142d9027470SGwendal Grignou 	{ ATA_DEV_PMP,			"pmp" },
143d9027470SGwendal Grignou 	{ ATA_DEV_PMP_UNSUP,		"pmp" },
144d9027470SGwendal Grignou 	{ ATA_DEV_SEMB,			"semb" },
145d9027470SGwendal Grignou 	{ ATA_DEV_SEMB_UNSUP,		"semb" },
1469162c657SHannes Reinecke 	{ ATA_DEV_ZAC,			"zac" },
147d9027470SGwendal Grignou 	{ ATA_DEV_NONE,			"none" }
148d9027470SGwendal Grignou };
149d9027470SGwendal Grignou ata_bitfield_name_search(class, ata_class_names)
150d9027470SGwendal Grignou 
151d9027470SGwendal Grignou 
152d9027470SGwendal Grignou static struct {
153d9027470SGwendal Grignou 	u32		value;
154d9027470SGwendal Grignou 	char		*name;
155d9027470SGwendal Grignou } ata_err_names[] = {
156d9027470SGwendal Grignou 	{ AC_ERR_DEV,			"DeviceError" },
157d9027470SGwendal Grignou 	{ AC_ERR_HSM,			"HostStateMachineError" },
158d9027470SGwendal Grignou 	{ AC_ERR_TIMEOUT,		"Timeout" },
159d9027470SGwendal Grignou 	{ AC_ERR_MEDIA,			"MediaError" },
160d9027470SGwendal Grignou 	{ AC_ERR_ATA_BUS,		"BusError" },
161d9027470SGwendal Grignou 	{ AC_ERR_HOST_BUS,		"HostBusError" },
162d9027470SGwendal Grignou 	{ AC_ERR_SYSTEM,		"SystemError" },
163d9027470SGwendal Grignou 	{ AC_ERR_INVALID,		"InvalidArg" },
164d9027470SGwendal Grignou 	{ AC_ERR_OTHER,			"Unknown" },
165d9027470SGwendal Grignou 	{ AC_ERR_NODEV_HINT,		"NoDeviceHint" },
166d9027470SGwendal Grignou 	{ AC_ERR_NCQ,			"NCQError" }
167d9027470SGwendal Grignou };
168d9027470SGwendal Grignou ata_bitfield_name_match(err, ata_err_names)
169d9027470SGwendal Grignou 
170d9027470SGwendal Grignou static struct {
171d9027470SGwendal Grignou 	u32		value;
172d9027470SGwendal Grignou 	char		*name;
173d9027470SGwendal Grignou } ata_xfer_names[] = {
174d9027470SGwendal Grignou 	{ XFER_UDMA_7,			"XFER_UDMA_7" },
175d9027470SGwendal Grignou 	{ XFER_UDMA_6,			"XFER_UDMA_6" },
176d9027470SGwendal Grignou 	{ XFER_UDMA_5,			"XFER_UDMA_5" },
177d9027470SGwendal Grignou 	{ XFER_UDMA_4,			"XFER_UDMA_4" },
178d9027470SGwendal Grignou 	{ XFER_UDMA_3,			"XFER_UDMA_3" },
179d9027470SGwendal Grignou 	{ XFER_UDMA_2,			"XFER_UDMA_2" },
180d9027470SGwendal Grignou 	{ XFER_UDMA_1,			"XFER_UDMA_1" },
181d9027470SGwendal Grignou 	{ XFER_UDMA_0,			"XFER_UDMA_0" },
182d9027470SGwendal Grignou 	{ XFER_MW_DMA_4,		"XFER_MW_DMA_4" },
183d9027470SGwendal Grignou 	{ XFER_MW_DMA_3,		"XFER_MW_DMA_3" },
184d9027470SGwendal Grignou 	{ XFER_MW_DMA_2,		"XFER_MW_DMA_2" },
185d9027470SGwendal Grignou 	{ XFER_MW_DMA_1,		"XFER_MW_DMA_1" },
186d9027470SGwendal Grignou 	{ XFER_MW_DMA_0,		"XFER_MW_DMA_0" },
187d9027470SGwendal Grignou 	{ XFER_SW_DMA_2,		"XFER_SW_DMA_2" },
188d9027470SGwendal Grignou 	{ XFER_SW_DMA_1,		"XFER_SW_DMA_1" },
189d9027470SGwendal Grignou 	{ XFER_SW_DMA_0,		"XFER_SW_DMA_0" },
190d9027470SGwendal Grignou 	{ XFER_PIO_6,			"XFER_PIO_6" },
191d9027470SGwendal Grignou 	{ XFER_PIO_5,			"XFER_PIO_5" },
192d9027470SGwendal Grignou 	{ XFER_PIO_4,			"XFER_PIO_4" },
193d9027470SGwendal Grignou 	{ XFER_PIO_3,			"XFER_PIO_3" },
194d9027470SGwendal Grignou 	{ XFER_PIO_2,			"XFER_PIO_2" },
195d9027470SGwendal Grignou 	{ XFER_PIO_1,			"XFER_PIO_1" },
196d9027470SGwendal Grignou 	{ XFER_PIO_0,			"XFER_PIO_0" },
197d9027470SGwendal Grignou 	{ XFER_PIO_SLOW,		"XFER_PIO_SLOW" }
198d9027470SGwendal Grignou };
19972aad489SSergey Shtylyov ata_bitfield_name_search(xfer, ata_xfer_names)
200d9027470SGwendal Grignou 
201d9027470SGwendal Grignou /*
202d9027470SGwendal Grignou  * ATA Port attributes
203d9027470SGwendal Grignou  */
204d9027470SGwendal Grignou #define ata_port_show_simple(field, name, format_string, cast)		\
205d9027470SGwendal Grignou static ssize_t								\
206d9027470SGwendal Grignou show_ata_port_##name(struct device *dev,				\
207d9027470SGwendal Grignou 		     struct device_attribute *attr, char *buf)		\
208d9027470SGwendal Grignou {									\
209d9027470SGwendal Grignou 	struct ata_port *ap = transport_class_to_port(dev);		\
210d9027470SGwendal Grignou 									\
211a900cc5cSTakashi Iwai 	return scnprintf(buf, 20, format_string, cast ap->field);	\
212d9027470SGwendal Grignou }
213d9027470SGwendal Grignou 
214d9027470SGwendal Grignou #define ata_port_simple_attr(field, name, format_string, type)		\
215d9027470SGwendal Grignou 	ata_port_show_simple(field, name, format_string, (type))	\
216d9027470SGwendal Grignou static DEVICE_ATTR(name, S_IRUGO, show_ata_port_##name, NULL)
217d9027470SGwendal Grignou 
218d9027470SGwendal Grignou ata_port_simple_attr(nr_pmp_links, nr_pmp_links, "%d\n", int);
219d9027470SGwendal Grignou ata_port_simple_attr(stats.idle_irq, idle_irq, "%ld\n", unsigned long);
220e628dc99SDavid Milburn ata_port_simple_attr(local_port_no, port_no, "%u\n", unsigned int);
221d9027470SGwendal Grignou 
222d9027470SGwendal Grignou static DECLARE_TRANSPORT_CLASS(ata_port_class,
223d9027470SGwendal Grignou 			       "ata_port", NULL, NULL, NULL);
224d9027470SGwendal Grignou 
ata_tport_release(struct device * dev)225d9027470SGwendal Grignou static void ata_tport_release(struct device *dev)
226d9027470SGwendal Grignou {
2272623c7a5STaras Kondratiuk 	struct ata_port *ap = tdev_to_port(dev);
2282623c7a5STaras Kondratiuk 	ata_host_put(ap->host);
229d9027470SGwendal Grignou }
230d9027470SGwendal Grignou 
231d9027470SGwendal Grignou /**
232d9027470SGwendal Grignou  * ata_is_port --  check if a struct device represents a ATA port
233d9027470SGwendal Grignou  * @dev:	device to check
234d9027470SGwendal Grignou  *
235d9027470SGwendal Grignou  * Returns:
236d9027470SGwendal Grignou  *	%1 if the device represents a ATA Port, %0 else
237d9027470SGwendal Grignou  */
ata_is_port(const struct device * dev)238b0e73af7SH Hartley Sweeten static int ata_is_port(const struct device *dev)
239d9027470SGwendal Grignou {
240d9027470SGwendal Grignou 	return dev->release == ata_tport_release;
241d9027470SGwendal Grignou }
242d9027470SGwendal Grignou 
ata_tport_match(struct attribute_container * cont,struct device * dev)243d9027470SGwendal Grignou static int ata_tport_match(struct attribute_container *cont,
244d9027470SGwendal Grignou 			   struct device *dev)
245d9027470SGwendal Grignou {
246d9027470SGwendal Grignou 	if (!ata_is_port(dev))
247d9027470SGwendal Grignou 		return 0;
248d9027470SGwendal Grignou 	return &ata_scsi_transport_template->host_attrs.ac == cont;
249d9027470SGwendal Grignou }
250d9027470SGwendal Grignou 
251d9027470SGwendal Grignou /**
252d9027470SGwendal Grignou  * ata_tport_delete  --  remove ATA PORT
253882184beSLee Jones  * @ap:	ATA PORT to remove
254d9027470SGwendal Grignou  *
255d9027470SGwendal Grignou  * Removes the specified ATA PORT.  Remove the associated link as well.
256d9027470SGwendal Grignou  */
ata_tport_delete(struct ata_port * ap)257d9027470SGwendal Grignou void ata_tport_delete(struct ata_port *ap)
258d9027470SGwendal Grignou {
259d9027470SGwendal Grignou 	struct device *dev = &ap->tdev;
260d9027470SGwendal Grignou 
261d9027470SGwendal Grignou 	ata_tlink_delete(&ap->link);
262d9027470SGwendal Grignou 
263d9027470SGwendal Grignou 	transport_remove_device(dev);
264d9027470SGwendal Grignou 	device_del(dev);
265d9027470SGwendal Grignou 	transport_destroy_device(dev);
266d9027470SGwendal Grignou 	put_device(dev);
267d9027470SGwendal Grignou }
268d9027470SGwendal Grignou 
269*75e2bd5fSDamien Le Moal static const struct device_type ata_port_sas_type = {
270*75e2bd5fSDamien Le Moal 	.name = ATA_PORT_TYPE_NAME,
271*75e2bd5fSDamien Le Moal };
272*75e2bd5fSDamien Le Moal 
273d9027470SGwendal Grignou /** ata_tport_add - initialize a transport ATA port structure
274d9027470SGwendal Grignou  *
275d9027470SGwendal Grignou  * @parent:	parent device
276d9027470SGwendal Grignou  * @ap:		existing ata_port structure
277d9027470SGwendal Grignou  *
278d9027470SGwendal Grignou  * Initialize a ATA port structure for sysfs.  It will be added to the device
279d9027470SGwendal Grignou  * tree below the device specified by @parent which could be a PCI device.
280d9027470SGwendal Grignou  *
281d9027470SGwendal Grignou  * Returns %0 on success
282d9027470SGwendal Grignou  */
ata_tport_add(struct device * parent,struct ata_port * ap)283d9027470SGwendal Grignou int ata_tport_add(struct device *parent,
284d9027470SGwendal Grignou 		  struct ata_port *ap)
285d9027470SGwendal Grignou {
286d9027470SGwendal Grignou 	int error;
287d9027470SGwendal Grignou 	struct device *dev = &ap->tdev;
288d9027470SGwendal Grignou 
289d9027470SGwendal Grignou 	device_initialize(dev);
290*75e2bd5fSDamien Le Moal 	if (ap->flags & ATA_FLAG_SAS_HOST)
291*75e2bd5fSDamien Le Moal 		dev->type = &ata_port_sas_type;
292*75e2bd5fSDamien Le Moal 	else
2935ef41082SLin Ming 		dev->type = &ata_port_type;
294d9027470SGwendal Grignou 
295d85fc67dSGwendal Grignou 	dev->parent = parent;
2962623c7a5STaras Kondratiuk 	ata_host_get(ap->host);
297d9027470SGwendal Grignou 	dev->release = ata_tport_release;
298d9027470SGwendal Grignou 	dev_set_name(dev, "ata%d", ap->print_id);
299d9027470SGwendal Grignou 	transport_setup_device(dev);
300f1bc1e4cSAaron Lu 	ata_acpi_bind_port(ap);
301d9027470SGwendal Grignou 	error = device_add(dev);
302d9027470SGwendal Grignou 	if (error) {
303d9027470SGwendal Grignou 		goto tport_err;
304d9027470SGwendal Grignou 	}
305d9027470SGwendal Grignou 
306966f1212SLin Ming 	device_enable_async_suspend(dev);
3079ee4f393SLin Ming 	pm_runtime_set_active(dev);
3089ee4f393SLin Ming 	pm_runtime_enable(dev);
3090c8d32c2SLin Ming 	pm_runtime_forbid(dev);
3109ee4f393SLin Ming 
3113613dbe3SYang Yingliang 	error = transport_add_device(dev);
3123613dbe3SYang Yingliang 	if (error)
3133613dbe3SYang Yingliang 		goto tport_transport_add_err;
314d9027470SGwendal Grignou 	transport_configure_device(dev);
315d9027470SGwendal Grignou 
316d9027470SGwendal Grignou 	error = ata_tlink_add(&ap->link);
317d9027470SGwendal Grignou 	if (error) {
318d9027470SGwendal Grignou 		goto tport_link_err;
319d9027470SGwendal Grignou 	}
320d9027470SGwendal Grignou 	return 0;
321d9027470SGwendal Grignou 
322d9027470SGwendal Grignou  tport_link_err:
323d9027470SGwendal Grignou 	transport_remove_device(dev);
3243613dbe3SYang Yingliang  tport_transport_add_err:
325d9027470SGwendal Grignou 	device_del(dev);
326d9027470SGwendal Grignou 
327d9027470SGwendal Grignou  tport_err:
328d9027470SGwendal Grignou 	transport_destroy_device(dev);
329d9027470SGwendal Grignou 	put_device(dev);
330d9027470SGwendal Grignou 	return error;
331d9027470SGwendal Grignou }
332d9027470SGwendal Grignou 
3336c952a0dSHannes Reinecke /**
3346c952a0dSHannes Reinecke  *     ata_port_classify - determine device type based on ATA-spec signature
3356c952a0dSHannes Reinecke  *     @ap: ATA port device on which the classification should be run
3366c952a0dSHannes Reinecke  *     @tf: ATA taskfile register set for device to be identified
3376c952a0dSHannes Reinecke  *
3386c952a0dSHannes Reinecke  *     A wrapper around ata_dev_classify() to provide additional logging
3396c952a0dSHannes Reinecke  *
3406c952a0dSHannes Reinecke  *     RETURNS:
3416c952a0dSHannes Reinecke  *     Device type, %ATA_DEV_ATA, %ATA_DEV_ATAPI, %ATA_DEV_PMP,
3426c952a0dSHannes Reinecke  *     %ATA_DEV_ZAC, or %ATA_DEV_UNKNOWN the event of failure.
3436c952a0dSHannes Reinecke  */
ata_port_classify(struct ata_port * ap,const struct ata_taskfile * tf)3446c952a0dSHannes Reinecke unsigned int ata_port_classify(struct ata_port *ap,
3456c952a0dSHannes Reinecke 			       const struct ata_taskfile *tf)
3466c952a0dSHannes Reinecke {
3476c952a0dSHannes Reinecke 	int i;
3486c952a0dSHannes Reinecke 	unsigned int class = ata_dev_classify(tf);
3496c952a0dSHannes Reinecke 
3506c952a0dSHannes Reinecke 	/* Start with index '1' to skip the 'unknown' entry */
3516c952a0dSHannes Reinecke 	for (i = 1; i < ARRAY_SIZE(ata_class_names); i++) {
3526c952a0dSHannes Reinecke 		if (ata_class_names[i].value == class) {
3536c952a0dSHannes Reinecke 			ata_port_dbg(ap, "found %s device by sig\n",
3546c952a0dSHannes Reinecke 				     ata_class_names[i].name);
3556c952a0dSHannes Reinecke 			return class;
3566c952a0dSHannes Reinecke 		}
3576c952a0dSHannes Reinecke 	}
3586c952a0dSHannes Reinecke 
3596c952a0dSHannes Reinecke 	ata_port_info(ap, "found unknown device (class %u)\n", class);
3606c952a0dSHannes Reinecke 	return class;
3616c952a0dSHannes Reinecke }
3626c952a0dSHannes Reinecke EXPORT_SYMBOL_GPL(ata_port_classify);
363d9027470SGwendal Grignou 
364d9027470SGwendal Grignou /*
365d9027470SGwendal Grignou  * ATA link attributes
366d9027470SGwendal Grignou  */
noop(int x)3673e85c3ecSGwendal Grignou static int noop(int x) { return x; }
368d9027470SGwendal Grignou 
3693e85c3ecSGwendal Grignou #define ata_link_show_linkspeed(field, format)				\
370d9027470SGwendal Grignou static ssize_t								\
371d9027470SGwendal Grignou show_ata_link_##field(struct device *dev,				\
372d9027470SGwendal Grignou 		      struct device_attribute *attr, char *buf)		\
373d9027470SGwendal Grignou {									\
374d9027470SGwendal Grignou 	struct ata_link *link = transport_class_to_link(dev);		\
375d9027470SGwendal Grignou 									\
3763e85c3ecSGwendal Grignou 	return sprintf(buf, "%s\n", sata_spd_string(format(link->field))); \
377d9027470SGwendal Grignou }
378d9027470SGwendal Grignou 
3793e85c3ecSGwendal Grignou #define ata_link_linkspeed_attr(field, format)				\
3803e85c3ecSGwendal Grignou 	ata_link_show_linkspeed(field, format)				\
381d9027470SGwendal Grignou static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL)
382d9027470SGwendal Grignou 
3833e85c3ecSGwendal Grignou ata_link_linkspeed_attr(hw_sata_spd_limit, fls);
3843e85c3ecSGwendal Grignou ata_link_linkspeed_attr(sata_spd_limit, fls);
3853e85c3ecSGwendal Grignou ata_link_linkspeed_attr(sata_spd, noop);
386d9027470SGwendal Grignou 
387d9027470SGwendal Grignou 
388d9027470SGwendal Grignou static DECLARE_TRANSPORT_CLASS(ata_link_class,
389d9027470SGwendal Grignou 		"ata_link", NULL, NULL, NULL);
390d9027470SGwendal Grignou 
ata_tlink_release(struct device * dev)391d9027470SGwendal Grignou static void ata_tlink_release(struct device *dev)
392d9027470SGwendal Grignou {
393d9027470SGwendal Grignou }
394d9027470SGwendal Grignou 
395d9027470SGwendal Grignou /**
396d9027470SGwendal Grignou  * ata_is_link --  check if a struct device represents a ATA link
397d9027470SGwendal Grignou  * @dev:	device to check
398d9027470SGwendal Grignou  *
399d9027470SGwendal Grignou  * Returns:
400d9027470SGwendal Grignou  *	%1 if the device represents a ATA link, %0 else
401d9027470SGwendal Grignou  */
ata_is_link(const struct device * dev)402b0e73af7SH Hartley Sweeten static int ata_is_link(const struct device *dev)
403d9027470SGwendal Grignou {
404d9027470SGwendal Grignou 	return dev->release == ata_tlink_release;
405d9027470SGwendal Grignou }
406d9027470SGwendal Grignou 
ata_tlink_match(struct attribute_container * cont,struct device * dev)407d9027470SGwendal Grignou static int ata_tlink_match(struct attribute_container *cont,
408d9027470SGwendal Grignou 			   struct device *dev)
409d9027470SGwendal Grignou {
410d9027470SGwendal Grignou 	struct ata_internal* i = to_ata_internal(ata_scsi_transport_template);
411d9027470SGwendal Grignou 	if (!ata_is_link(dev))
412d9027470SGwendal Grignou 		return 0;
413d9027470SGwendal Grignou 	return &i->link_attr_cont.ac == cont;
414d9027470SGwendal Grignou }
415d9027470SGwendal Grignou 
416d9027470SGwendal Grignou /**
417d9027470SGwendal Grignou  * ata_tlink_delete  --  remove ATA LINK
418882184beSLee Jones  * @link:	ATA LINK to remove
419d9027470SGwendal Grignou  *
420d9027470SGwendal Grignou  * Removes the specified ATA LINK.  remove associated ATA device(s) as well.
421d9027470SGwendal Grignou  */
ata_tlink_delete(struct ata_link * link)422d9027470SGwendal Grignou void ata_tlink_delete(struct ata_link *link)
423d9027470SGwendal Grignou {
424d9027470SGwendal Grignou 	struct device *dev = &link->tdev;
425d9027470SGwendal Grignou 	struct ata_device *ata_dev;
426d9027470SGwendal Grignou 
427d9027470SGwendal Grignou 	ata_for_each_dev(ata_dev, link, ALL) {
428d9027470SGwendal Grignou 		ata_tdev_delete(ata_dev);
429d9027470SGwendal Grignou 	}
430d9027470SGwendal Grignou 
431d9027470SGwendal Grignou 	transport_remove_device(dev);
432d9027470SGwendal Grignou 	device_del(dev);
433d9027470SGwendal Grignou 	transport_destroy_device(dev);
434d9027470SGwendal Grignou 	put_device(dev);
435d9027470SGwendal Grignou }
436d9027470SGwendal Grignou 
437d9027470SGwendal Grignou /**
438d9027470SGwendal Grignou  * ata_tlink_add  --  initialize a transport ATA link structure
439d9027470SGwendal Grignou  * @link:	allocated ata_link structure.
440d9027470SGwendal Grignou  *
441d9027470SGwendal Grignou  * Initialize an ATA LINK structure for sysfs.  It will be added in the
442d9027470SGwendal Grignou  * device tree below the ATA PORT it belongs to.
443d9027470SGwendal Grignou  *
444d9027470SGwendal Grignou  * Returns %0 on success
445d9027470SGwendal Grignou  */
ata_tlink_add(struct ata_link * link)446d9027470SGwendal Grignou int ata_tlink_add(struct ata_link *link)
447d9027470SGwendal Grignou {
448d9027470SGwendal Grignou 	struct device *dev = &link->tdev;
449d9027470SGwendal Grignou 	struct ata_port *ap = link->ap;
450d9027470SGwendal Grignou 	struct ata_device *ata_dev;
451d9027470SGwendal Grignou 	int error;
452d9027470SGwendal Grignou 
453d9027470SGwendal Grignou 	device_initialize(dev);
454d85fc67dSGwendal Grignou 	dev->parent = &ap->tdev;
455d9027470SGwendal Grignou 	dev->release = ata_tlink_release;
456d9027470SGwendal Grignou 	if (ata_is_host_link(link))
457d9027470SGwendal Grignou 		dev_set_name(dev, "link%d", ap->print_id);
458d9027470SGwendal Grignou 	else
459d9027470SGwendal Grignou 		dev_set_name(dev, "link%d.%d", ap->print_id, link->pmp);
460d9027470SGwendal Grignou 
461d9027470SGwendal Grignou 	transport_setup_device(dev);
462d9027470SGwendal Grignou 
463d9027470SGwendal Grignou 	error = device_add(dev);
464d9027470SGwendal Grignou 	if (error) {
465d9027470SGwendal Grignou 		goto tlink_err;
466d9027470SGwendal Grignou 	}
467d9027470SGwendal Grignou 
468cf0816f6SYang Yingliang 	error = transport_add_device(dev);
469cf0816f6SYang Yingliang 	if (error)
470cf0816f6SYang Yingliang 		goto tlink_transport_err;
471d9027470SGwendal Grignou 	transport_configure_device(dev);
472d9027470SGwendal Grignou 
473d9027470SGwendal Grignou 	ata_for_each_dev(ata_dev, link, ALL) {
474d9027470SGwendal Grignou 		error = ata_tdev_add(ata_dev);
475d9027470SGwendal Grignou 		if (error) {
476d9027470SGwendal Grignou 			goto tlink_dev_err;
477d9027470SGwendal Grignou 		}
478d9027470SGwendal Grignou 	}
479d9027470SGwendal Grignou 	return 0;
480d9027470SGwendal Grignou   tlink_dev_err:
481d9027470SGwendal Grignou 	while (--ata_dev >= link->device) {
482d9027470SGwendal Grignou 		ata_tdev_delete(ata_dev);
483d9027470SGwendal Grignou 	}
484d9027470SGwendal Grignou 	transport_remove_device(dev);
485cf0816f6SYang Yingliang   tlink_transport_err:
486d9027470SGwendal Grignou 	device_del(dev);
487d9027470SGwendal Grignou   tlink_err:
488d9027470SGwendal Grignou 	transport_destroy_device(dev);
489d9027470SGwendal Grignou 	put_device(dev);
490d9027470SGwendal Grignou 	return error;
491d9027470SGwendal Grignou }
492d9027470SGwendal Grignou 
493d9027470SGwendal Grignou /*
494d9027470SGwendal Grignou  * ATA device attributes
495d9027470SGwendal Grignou  */
496d9027470SGwendal Grignou 
497d9027470SGwendal Grignou #define ata_dev_show_class(title, field)				\
498d9027470SGwendal Grignou static ssize_t								\
499d9027470SGwendal Grignou show_ata_dev_##field(struct device *dev,				\
500d9027470SGwendal Grignou 		     struct device_attribute *attr, char *buf)		\
501d9027470SGwendal Grignou {									\
502d9027470SGwendal Grignou 	struct ata_device *ata_dev = transport_class_to_dev(dev);	\
503d9027470SGwendal Grignou 									\
504d9027470SGwendal Grignou 	return get_ata_##title##_names(ata_dev->field, buf);		\
505d9027470SGwendal Grignou }
506d9027470SGwendal Grignou 
507d9027470SGwendal Grignou #define ata_dev_attr(title, field)					\
508d9027470SGwendal Grignou 	ata_dev_show_class(title, field)				\
509d9027470SGwendal Grignou static DEVICE_ATTR(field, S_IRUGO, show_ata_dev_##field, NULL)
510d9027470SGwendal Grignou 
511d9027470SGwendal Grignou ata_dev_attr(class, class);
512d9027470SGwendal Grignou ata_dev_attr(xfer, pio_mode);
513d9027470SGwendal Grignou ata_dev_attr(xfer, dma_mode);
514d9027470SGwendal Grignou ata_dev_attr(xfer, xfer_mode);
515d9027470SGwendal Grignou 
516d9027470SGwendal Grignou 
517d9027470SGwendal Grignou #define ata_dev_show_simple(field, format_string, cast)			\
518d9027470SGwendal Grignou static ssize_t								\
519d9027470SGwendal Grignou show_ata_dev_##field(struct device *dev,				\
520d9027470SGwendal Grignou 		     struct device_attribute *attr, char *buf)		\
521d9027470SGwendal Grignou {									\
522d9027470SGwendal Grignou 	struct ata_device *ata_dev = transport_class_to_dev(dev);	\
523d9027470SGwendal Grignou 									\
524a900cc5cSTakashi Iwai 	return scnprintf(buf, 20, format_string, cast ata_dev->field);	\
525d9027470SGwendal Grignou }
526d9027470SGwendal Grignou 
527d9027470SGwendal Grignou #define ata_dev_simple_attr(field, format_string, type)		\
528d9027470SGwendal Grignou 	ata_dev_show_simple(field, format_string, (type))	\
529d9027470SGwendal Grignou 	static DEVICE_ATTR(field, S_IRUGO,			\
530d9027470SGwendal Grignou 		   show_ata_dev_##field, NULL)
531d9027470SGwendal Grignou 
532d9027470SGwendal Grignou ata_dev_simple_attr(spdn_cnt, "%d\n", int);
533d9027470SGwendal Grignou 
534d9027470SGwendal Grignou struct ata_show_ering_arg {
535d9027470SGwendal Grignou 	char* buf;
536d9027470SGwendal Grignou 	int written;
537d9027470SGwendal Grignou };
538d9027470SGwendal Grignou 
ata_show_ering(struct ata_ering_entry * ent,void * void_arg)539d9027470SGwendal Grignou static int ata_show_ering(struct ata_ering_entry *ent, void *void_arg)
540d9027470SGwendal Grignou {
541d9027470SGwendal Grignou 	struct ata_show_ering_arg* arg = void_arg;
542f3f99d37SArnd Bergmann 	u64 seconds;
543f3f99d37SArnd Bergmann 	u32 rem;
544d9027470SGwendal Grignou 
545f3f99d37SArnd Bergmann 	seconds = div_u64_rem(ent->timestamp, HZ, &rem);
546d9027470SGwendal Grignou 	arg->written += sprintf(arg->buf + arg->written,
547f3f99d37SArnd Bergmann 				"[%5llu.%09lu]", seconds,
548f3f99d37SArnd Bergmann 				rem * NSEC_PER_SEC / HZ);
549d9027470SGwendal Grignou 	arg->written += get_ata_err_names(ent->err_mask,
550d9027470SGwendal Grignou 					  arg->buf + arg->written);
551d9027470SGwendal Grignou 	return 0;
552d9027470SGwendal Grignou }
553d9027470SGwendal Grignou 
554d9027470SGwendal Grignou static ssize_t
show_ata_dev_ering(struct device * dev,struct device_attribute * attr,char * buf)555d9027470SGwendal Grignou show_ata_dev_ering(struct device *dev,
556d9027470SGwendal Grignou 		   struct device_attribute *attr, char *buf)
557d9027470SGwendal Grignou {
558d9027470SGwendal Grignou 	struct ata_device *ata_dev = transport_class_to_dev(dev);
559d9027470SGwendal Grignou 	struct ata_show_ering_arg arg = { buf, 0 };
560d9027470SGwendal Grignou 
561d9027470SGwendal Grignou 	ata_ering_map(&ata_dev->ering, ata_show_ering, &arg);
562d9027470SGwendal Grignou 	return arg.written;
563d9027470SGwendal Grignou }
564d9027470SGwendal Grignou 
565d9027470SGwendal Grignou 
566d9027470SGwendal Grignou static DEVICE_ATTR(ering, S_IRUGO, show_ata_dev_ering, NULL);
567d9027470SGwendal Grignou 
568d9027470SGwendal Grignou static ssize_t
show_ata_dev_id(struct device * dev,struct device_attribute * attr,char * buf)569d9027470SGwendal Grignou show_ata_dev_id(struct device *dev,
570d9027470SGwendal Grignou 		struct device_attribute *attr, char *buf)
571d9027470SGwendal Grignou {
572d9027470SGwendal Grignou 	struct ata_device *ata_dev = transport_class_to_dev(dev);
573d9027470SGwendal Grignou 	int written = 0, i = 0;
574d9027470SGwendal Grignou 
575d9027470SGwendal Grignou 	if (ata_dev->class == ATA_DEV_PMP)
576d9027470SGwendal Grignou 		return 0;
577d9027470SGwendal Grignou 	for(i=0;i<ATA_ID_WORDS;i++)  {
578a900cc5cSTakashi Iwai 		written += scnprintf(buf+written, 20, "%04x%c",
579d9027470SGwendal Grignou 				    ata_dev->id[i],
580d9027470SGwendal Grignou 				    ((i+1) & 7) ? ' ' : '\n');
581d9027470SGwendal Grignou 	}
582d9027470SGwendal Grignou 	return written;
583d9027470SGwendal Grignou }
584d9027470SGwendal Grignou 
585d9027470SGwendal Grignou static DEVICE_ATTR(id, S_IRUGO, show_ata_dev_id, NULL);
586d9027470SGwendal Grignou 
587d9027470SGwendal Grignou static ssize_t
show_ata_dev_gscr(struct device * dev,struct device_attribute * attr,char * buf)588d9027470SGwendal Grignou show_ata_dev_gscr(struct device *dev,
589d9027470SGwendal Grignou 		  struct device_attribute *attr, char *buf)
590d9027470SGwendal Grignou {
591d9027470SGwendal Grignou 	struct ata_device *ata_dev = transport_class_to_dev(dev);
592d9027470SGwendal Grignou 	int written = 0, i = 0;
593d9027470SGwendal Grignou 
594d9027470SGwendal Grignou 	if (ata_dev->class != ATA_DEV_PMP)
595d9027470SGwendal Grignou 		return 0;
596d9027470SGwendal Grignou 	for(i=0;i<SATA_PMP_GSCR_DWORDS;i++)  {
597a900cc5cSTakashi Iwai 		written += scnprintf(buf+written, 20, "%08x%c",
598d9027470SGwendal Grignou 				    ata_dev->gscr[i],
599d9027470SGwendal Grignou 				    ((i+1) & 3) ? ' ' : '\n');
600d9027470SGwendal Grignou 	}
601d9027470SGwendal Grignou 	if (SATA_PMP_GSCR_DWORDS & 3)
602d9027470SGwendal Grignou 		buf[written-1] = '\n';
603d9027470SGwendal Grignou 	return written;
604d9027470SGwendal Grignou }
605d9027470SGwendal Grignou 
606d9027470SGwendal Grignou static DEVICE_ATTR(gscr, S_IRUGO, show_ata_dev_gscr, NULL);
607d9027470SGwendal Grignou 
608f3030741SMartin K. Petersen static ssize_t
show_ata_dev_trim(struct device * dev,struct device_attribute * attr,char * buf)609f3030741SMartin K. Petersen show_ata_dev_trim(struct device *dev,
610f3030741SMartin K. Petersen 		  struct device_attribute *attr, char *buf)
611f3030741SMartin K. Petersen {
612f3030741SMartin K. Petersen 	struct ata_device *ata_dev = transport_class_to_dev(dev);
613f3030741SMartin K. Petersen 	unsigned char *mode;
614f3030741SMartin K. Petersen 
615f3030741SMartin K. Petersen 	if (!ata_id_has_trim(ata_dev->id))
616f3030741SMartin K. Petersen 		mode = "unsupported";
61771d126fdSArne Fitzenreiter 	else if (ata_dev->horkage & ATA_HORKAGE_NOTRIM)
61871d126fdSArne Fitzenreiter 		mode = "forced_unsupported";
619f3030741SMartin K. Petersen 	else if (ata_dev->horkage & ATA_HORKAGE_NO_NCQ_TRIM)
620f3030741SMartin K. Petersen 			mode = "forced_unqueued";
621f3030741SMartin K. Petersen 	else if (ata_fpdma_dsm_supported(ata_dev))
622f3030741SMartin K. Petersen 		mode = "queued";
623f3030741SMartin K. Petersen 	else
624f3030741SMartin K. Petersen 		mode = "unqueued";
625f3030741SMartin K. Petersen 
626a900cc5cSTakashi Iwai 	return scnprintf(buf, 20, "%s\n", mode);
627f3030741SMartin K. Petersen }
628f3030741SMartin K. Petersen 
629f3030741SMartin K. Petersen static DEVICE_ATTR(trim, S_IRUGO, show_ata_dev_trim, NULL);
630f3030741SMartin K. Petersen 
631d9027470SGwendal Grignou static DECLARE_TRANSPORT_CLASS(ata_dev_class,
632d9027470SGwendal Grignou 			       "ata_device", NULL, NULL, NULL);
633d9027470SGwendal Grignou 
ata_tdev_release(struct device * dev)634d9027470SGwendal Grignou static void ata_tdev_release(struct device *dev)
635d9027470SGwendal Grignou {
636d9027470SGwendal Grignou }
637d9027470SGwendal Grignou 
638d9027470SGwendal Grignou /**
639d9027470SGwendal Grignou  * ata_is_ata_dev  --  check if a struct device represents a ATA device
640d9027470SGwendal Grignou  * @dev:	device to check
641d9027470SGwendal Grignou  *
642d9027470SGwendal Grignou  * Returns:
643d9027470SGwendal Grignou  *	%1 if the device represents a ATA device, %0 else
644d9027470SGwendal Grignou  */
ata_is_ata_dev(const struct device * dev)645b0e73af7SH Hartley Sweeten static int ata_is_ata_dev(const struct device *dev)
646d9027470SGwendal Grignou {
647d9027470SGwendal Grignou 	return dev->release == ata_tdev_release;
648d9027470SGwendal Grignou }
649d9027470SGwendal Grignou 
ata_tdev_match(struct attribute_container * cont,struct device * dev)650d9027470SGwendal Grignou static int ata_tdev_match(struct attribute_container *cont,
651d9027470SGwendal Grignou 			  struct device *dev)
652d9027470SGwendal Grignou {
653d9027470SGwendal Grignou 	struct ata_internal* i = to_ata_internal(ata_scsi_transport_template);
654d9027470SGwendal Grignou 	if (!ata_is_ata_dev(dev))
655d9027470SGwendal Grignou 		return 0;
656d9027470SGwendal Grignou 	return &i->dev_attr_cont.ac == cont;
657d9027470SGwendal Grignou }
658d9027470SGwendal Grignou 
659d9027470SGwendal Grignou /**
660d9027470SGwendal Grignou  * ata_tdev_free  --  free a ATA LINK
661d9027470SGwendal Grignou  * @dev:	ATA PHY to free
662d9027470SGwendal Grignou  *
663d9027470SGwendal Grignou  * Frees the specified ATA PHY.
664d9027470SGwendal Grignou  *
665d9027470SGwendal Grignou  * Note:
666d9027470SGwendal Grignou  *   This function must only be called on a PHY that has not
667d9027470SGwendal Grignou  *   successfully been added using ata_tdev_add().
668d9027470SGwendal Grignou  */
ata_tdev_free(struct ata_device * dev)669d9027470SGwendal Grignou static void ata_tdev_free(struct ata_device *dev)
670d9027470SGwendal Grignou {
671d9027470SGwendal Grignou 	transport_destroy_device(&dev->tdev);
672d9027470SGwendal Grignou 	put_device(&dev->tdev);
673d9027470SGwendal Grignou }
674d9027470SGwendal Grignou 
675d9027470SGwendal Grignou /**
676d9027470SGwendal Grignou  * ata_tdev_delete  --  remove ATA device
677882184beSLee Jones  * @ata_dev:	ATA device to remove
678d9027470SGwendal Grignou  *
679d9027470SGwendal Grignou  * Removes the specified ATA device.
680d9027470SGwendal Grignou  */
ata_tdev_delete(struct ata_device * ata_dev)681d9027470SGwendal Grignou static void ata_tdev_delete(struct ata_device *ata_dev)
682d9027470SGwendal Grignou {
683d9027470SGwendal Grignou 	struct device *dev = &ata_dev->tdev;
684d9027470SGwendal Grignou 
685d9027470SGwendal Grignou 	transport_remove_device(dev);
686d9027470SGwendal Grignou 	device_del(dev);
687d9027470SGwendal Grignou 	ata_tdev_free(ata_dev);
688d9027470SGwendal Grignou }
689d9027470SGwendal Grignou 
690d9027470SGwendal Grignou 
691d9027470SGwendal Grignou /**
692d9027470SGwendal Grignou  * ata_tdev_add  --  initialize a transport ATA device structure.
693d9027470SGwendal Grignou  * @ata_dev:	ata_dev structure.
694d9027470SGwendal Grignou  *
695d9027470SGwendal Grignou  * Initialize an ATA device structure for sysfs.  It will be added in the
696d9027470SGwendal Grignou  * device tree below the ATA LINK device it belongs to.
697d9027470SGwendal Grignou  *
698d9027470SGwendal Grignou  * Returns %0 on success
699d9027470SGwendal Grignou  */
ata_tdev_add(struct ata_device * ata_dev)700d9027470SGwendal Grignou static int ata_tdev_add(struct ata_device *ata_dev)
701d9027470SGwendal Grignou {
702d9027470SGwendal Grignou 	struct device *dev = &ata_dev->tdev;
703d9027470SGwendal Grignou 	struct ata_link *link = ata_dev->link;
704d9027470SGwendal Grignou 	struct ata_port *ap = link->ap;
705d9027470SGwendal Grignou 	int error;
706d9027470SGwendal Grignou 
707d9027470SGwendal Grignou 	device_initialize(dev);
708d85fc67dSGwendal Grignou 	dev->parent = &link->tdev;
709d9027470SGwendal Grignou 	dev->release = ata_tdev_release;
710d9027470SGwendal Grignou 	if (ata_is_host_link(link))
711d9027470SGwendal Grignou 		dev_set_name(dev, "dev%d.%d", ap->print_id,ata_dev->devno);
712d9027470SGwendal Grignou 	else
713d9027470SGwendal Grignou 		dev_set_name(dev, "dev%d.%d.0", ap->print_id, link->pmp);
714d9027470SGwendal Grignou 
715d9027470SGwendal Grignou 	transport_setup_device(dev);
716f1bc1e4cSAaron Lu 	ata_acpi_bind_dev(ata_dev);
717d9027470SGwendal Grignou 	error = device_add(dev);
718d9027470SGwendal Grignou 	if (error) {
719d9027470SGwendal Grignou 		ata_tdev_free(ata_dev);
720d9027470SGwendal Grignou 		return error;
721d9027470SGwendal Grignou 	}
722d9027470SGwendal Grignou 
7231ff36351SYang Yingliang 	error = transport_add_device(dev);
7241ff36351SYang Yingliang 	if (error) {
7251ff36351SYang Yingliang 		device_del(dev);
7261ff36351SYang Yingliang 		ata_tdev_free(ata_dev);
7271ff36351SYang Yingliang 		return error;
7281ff36351SYang Yingliang 	}
7291ff36351SYang Yingliang 
730d9027470SGwendal Grignou 	transport_configure_device(dev);
731d9027470SGwendal Grignou 	return 0;
732d9027470SGwendal Grignou }
733d9027470SGwendal Grignou 
734d9027470SGwendal Grignou 
735d9027470SGwendal Grignou /*
736d9027470SGwendal Grignou  * Setup / Teardown code
737d9027470SGwendal Grignou  */
738d9027470SGwendal Grignou 
739d9027470SGwendal Grignou #define SETUP_TEMPLATE(attrb, field, perm, test)			\
740d9027470SGwendal Grignou 	i->private_##attrb[count] = dev_attr_##field;			\
741d9027470SGwendal Grignou 	i->private_##attrb[count].attr.mode = perm;			\
742d9027470SGwendal Grignou 	i->attrb[count] = &i->private_##attrb[count];			\
743d9027470SGwendal Grignou 	if (test)							\
744d9027470SGwendal Grignou 		count++
745d9027470SGwendal Grignou 
746d9027470SGwendal Grignou #define SETUP_LINK_ATTRIBUTE(field)					\
747d9027470SGwendal Grignou 	SETUP_TEMPLATE(link_attrs, field, S_IRUGO, 1)
748d9027470SGwendal Grignou 
749d9027470SGwendal Grignou #define SETUP_PORT_ATTRIBUTE(field)					\
750d9027470SGwendal Grignou 	SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1)
751d9027470SGwendal Grignou 
752d9027470SGwendal Grignou #define SETUP_DEV_ATTRIBUTE(field)					\
753d9027470SGwendal Grignou 	SETUP_TEMPLATE(dev_attrs, field, S_IRUGO, 1)
754d9027470SGwendal Grignou 
755d9027470SGwendal Grignou /**
756d9027470SGwendal Grignou  * ata_attach_transport  --  instantiate ATA transport template
757d9027470SGwendal Grignou  */
ata_attach_transport(void)758d9027470SGwendal Grignou struct scsi_transport_template *ata_attach_transport(void)
759d9027470SGwendal Grignou {
760d9027470SGwendal Grignou 	struct ata_internal *i;
761d9027470SGwendal Grignou 	int count;
762d9027470SGwendal Grignou 
763d9027470SGwendal Grignou 	i = kzalloc(sizeof(struct ata_internal), GFP_KERNEL);
764d9027470SGwendal Grignou 	if (!i)
765d9027470SGwendal Grignou 		return NULL;
766d9027470SGwendal Grignou 
767d9027470SGwendal Grignou 	i->t.eh_strategy_handler	= ata_scsi_error;
768d9027470SGwendal Grignou 	i->t.user_scan			= ata_scsi_user_scan;
769d9027470SGwendal Grignou 
770d9027470SGwendal Grignou 	i->t.host_attrs.ac.attrs = &i->port_attrs[0];
771d9027470SGwendal Grignou 	i->t.host_attrs.ac.class = &ata_port_class.class;
772d9027470SGwendal Grignou 	i->t.host_attrs.ac.match = ata_tport_match;
773d9027470SGwendal Grignou 	transport_container_register(&i->t.host_attrs);
774d9027470SGwendal Grignou 
775d9027470SGwendal Grignou 	i->link_attr_cont.ac.class = &ata_link_class.class;
776d9027470SGwendal Grignou 	i->link_attr_cont.ac.attrs = &i->link_attrs[0];
777d9027470SGwendal Grignou 	i->link_attr_cont.ac.match = ata_tlink_match;
778d9027470SGwendal Grignou 	transport_container_register(&i->link_attr_cont);
779d9027470SGwendal Grignou 
780d9027470SGwendal Grignou 	i->dev_attr_cont.ac.class = &ata_dev_class.class;
781d9027470SGwendal Grignou 	i->dev_attr_cont.ac.attrs = &i->dev_attrs[0];
782d9027470SGwendal Grignou 	i->dev_attr_cont.ac.match = ata_tdev_match;
783d9027470SGwendal Grignou 	transport_container_register(&i->dev_attr_cont);
784d9027470SGwendal Grignou 
785d9027470SGwendal Grignou 	count = 0;
786d9027470SGwendal Grignou 	SETUP_PORT_ATTRIBUTE(nr_pmp_links);
787d9027470SGwendal Grignou 	SETUP_PORT_ATTRIBUTE(idle_irq);
788e628dc99SDavid Milburn 	SETUP_PORT_ATTRIBUTE(port_no);
789d9027470SGwendal Grignou 	BUG_ON(count > ATA_PORT_ATTRS);
790d9027470SGwendal Grignou 	i->port_attrs[count] = NULL;
791d9027470SGwendal Grignou 
792d9027470SGwendal Grignou 	count = 0;
793d9027470SGwendal Grignou 	SETUP_LINK_ATTRIBUTE(hw_sata_spd_limit);
794d9027470SGwendal Grignou 	SETUP_LINK_ATTRIBUTE(sata_spd_limit);
795d9027470SGwendal Grignou 	SETUP_LINK_ATTRIBUTE(sata_spd);
796d9027470SGwendal Grignou 	BUG_ON(count > ATA_LINK_ATTRS);
797d9027470SGwendal Grignou 	i->link_attrs[count] = NULL;
798d9027470SGwendal Grignou 
799d9027470SGwendal Grignou 	count = 0;
800d9027470SGwendal Grignou 	SETUP_DEV_ATTRIBUTE(class);
801d9027470SGwendal Grignou 	SETUP_DEV_ATTRIBUTE(pio_mode);
802d9027470SGwendal Grignou 	SETUP_DEV_ATTRIBUTE(dma_mode);
803d9027470SGwendal Grignou 	SETUP_DEV_ATTRIBUTE(xfer_mode);
804d9027470SGwendal Grignou 	SETUP_DEV_ATTRIBUTE(spdn_cnt);
805d9027470SGwendal Grignou 	SETUP_DEV_ATTRIBUTE(ering);
806d9027470SGwendal Grignou 	SETUP_DEV_ATTRIBUTE(id);
807d9027470SGwendal Grignou 	SETUP_DEV_ATTRIBUTE(gscr);
808f3030741SMartin K. Petersen 	SETUP_DEV_ATTRIBUTE(trim);
809d9027470SGwendal Grignou 	BUG_ON(count > ATA_DEV_ATTRS);
810d9027470SGwendal Grignou 	i->dev_attrs[count] = NULL;
811d9027470SGwendal Grignou 
812d9027470SGwendal Grignou 	return &i->t;
813d9027470SGwendal Grignou }
814d9027470SGwendal Grignou 
815d9027470SGwendal Grignou /**
816d9027470SGwendal Grignou  * ata_release_transport  --  release ATA transport template instance
817d9027470SGwendal Grignou  * @t:		transport template instance
818d9027470SGwendal Grignou  */
ata_release_transport(struct scsi_transport_template * t)819d9027470SGwendal Grignou void ata_release_transport(struct scsi_transport_template *t)
820d9027470SGwendal Grignou {
821d9027470SGwendal Grignou 	struct ata_internal *i = to_ata_internal(t);
822d9027470SGwendal Grignou 
823d9027470SGwendal Grignou 	transport_container_unregister(&i->t.host_attrs);
824d9027470SGwendal Grignou 	transport_container_unregister(&i->link_attr_cont);
825d9027470SGwendal Grignou 	transport_container_unregister(&i->dev_attr_cont);
826d9027470SGwendal Grignou 
827d9027470SGwendal Grignou 	kfree(i);
828d9027470SGwendal Grignou }
829d9027470SGwendal Grignou 
libata_transport_init(void)830d9027470SGwendal Grignou __init int libata_transport_init(void)
831d9027470SGwendal Grignou {
832d9027470SGwendal Grignou 	int error;
833d9027470SGwendal Grignou 
834d9027470SGwendal Grignou 	error = transport_class_register(&ata_link_class);
835d9027470SGwendal Grignou 	if (error)
836d9027470SGwendal Grignou 		goto out_unregister_transport;
837d9027470SGwendal Grignou 	error = transport_class_register(&ata_port_class);
838d9027470SGwendal Grignou 	if (error)
839d9027470SGwendal Grignou 		goto out_unregister_link;
840d9027470SGwendal Grignou 	error = transport_class_register(&ata_dev_class);
841d9027470SGwendal Grignou 	if (error)
842d9027470SGwendal Grignou 		goto out_unregister_port;
843d9027470SGwendal Grignou 	return 0;
844d9027470SGwendal Grignou 
845d9027470SGwendal Grignou  out_unregister_port:
846d9027470SGwendal Grignou 	transport_class_unregister(&ata_port_class);
847d9027470SGwendal Grignou  out_unregister_link:
848d9027470SGwendal Grignou 	transport_class_unregister(&ata_link_class);
849d9027470SGwendal Grignou  out_unregister_transport:
850d9027470SGwendal Grignou 	return error;
851d9027470SGwendal Grignou 
852d9027470SGwendal Grignou }
853d9027470SGwendal Grignou 
libata_transport_exit(void)854d9027470SGwendal Grignou void __exit libata_transport_exit(void)
855d9027470SGwendal Grignou {
856d9027470SGwendal Grignou 	transport_class_unregister(&ata_link_class);
857d9027470SGwendal Grignou 	transport_class_unregister(&ata_port_class);
858d9027470SGwendal Grignou 	transport_class_unregister(&ata_dev_class);
859d9027470SGwendal Grignou }
860