]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-libata-ahci-pm.patch
- unconditional noarch packages
[packages/kernel.git] / kernel-libata-ahci-pm.patch
CommitLineData
e8791d4f
AM
1diff -urNp -x '*.orig' linux-4.9/Documentation/scsi/link_power_management_policy.txt linux-4.9/Documentation/scsi/link_power_management_policy.txt
2--- linux-4.9/Documentation/scsi/link_power_management_policy.txt 2016-12-11 20:17:54.000000000 +0100
3+++ linux-4.9/Documentation/scsi/link_power_management_policy.txt 2021-02-24 16:30:09.260516752 +0100
4@@ -1,8 +1,11 @@
5 This parameter allows the user to set the link (interface) power management.
6-There are 3 possible options:
7+There are 4 possible options:
8
9 Value Effect
10 ----------------------------------------------------------------------------
11+firmware_defaults Inherit configuration from the state programmed by
12+ the firmware during system init.
13+
14 min_power Tell the controller to try to make the link use the
15 least possible power when possible. This may
16 sacrifice some performance due to increased latency
17diff -urNp -x '*.orig' linux-4.9/drivers/ata/acard-ahci.c linux-4.9/drivers/ata/acard-ahci.c
18--- linux-4.9/drivers/ata/acard-ahci.c 2021-02-24 16:29:54.606714867 +0100
19+++ linux-4.9/drivers/ata/acard-ahci.c 2021-02-24 16:30:09.257183312 +0100
20@@ -480,6 +480,9 @@ static int acard_ahci_init_one(struct pc
2155c5a2
JR
21 ata_port_pbar_desc(ap, AHCI_PCI_BAR,
22 0x100 + ap->port_no * 0x80, "port");
23
24+ rc = ahci_setup_port_privdata(ap);
25+ if (rc)
26+ return rc;
27 /* set initial link pm policy */
28 /*
29 ap->pm_policy = NOT_AVAILABLE;
e8791d4f
AM
30diff -urNp -x '*.orig' linux-4.9/drivers/ata/ahci.c linux-4.9/drivers/ata/ahci.c
31--- linux-4.9/drivers/ata/ahci.c 2021-02-24 16:29:54.606714867 +0100
32+++ linux-4.9/drivers/ata/ahci.c 2021-02-24 16:30:09.257183312 +0100
33@@ -1743,6 +1743,9 @@ static int ahci_init_one(struct pci_dev
2155c5a2
JR
34 if (ap->flags & ATA_FLAG_EM)
35 ap->em_message_type = hpriv->em_msg_type;
36
37+ rc = ahci_setup_port_privdata(ap);
38+ if (rc)
39+ return rc;
40
41 /* disabled/not-implemented port */
42 if (!(hpriv->port_map & (1 << i)))
e8791d4f
AM
43diff -urNp -x '*.orig' linux-4.9/drivers/ata/ahci.h linux-4.9/drivers/ata/ahci.h
44--- linux-4.9/drivers/ata/ahci.h 2016-12-11 20:17:54.000000000 +0100
45+++ linux-4.9/drivers/ata/ahci.h 2021-02-24 16:30:09.257183312 +0100
46@@ -322,6 +322,12 @@ struct ahci_port_priv {
2155c5a2
JR
47 /* enclosure management info per PM slot */
48 struct ahci_em_priv em_priv[EM_MAX_SLOTS];
49 char *irq_desc; /* desc in /proc/interrupts */
50+ bool init_alpe; /* alpe enabled by default */
51+ bool init_asp; /* asp enabled by default */
52+ bool init_devslp; /* devslp enabled by default */
53+ u32 init_dito; /* initial dito configuration */
54+ u32 init_deto; /* initial deto configuration */
55+ u32 init_mdat; /* initial mdat configuration */
56 };
57
58 struct ahci_host_priv {
e8791d4f 59@@ -387,6 +393,7 @@ extern struct ata_port_operations ahci_p
2155c5a2
JR
60 extern struct ata_port_operations ahci_pmp_retry_srst_ops;
61
62 unsigned int ahci_dev_classify(struct ata_port *ap);
63+int ahci_setup_port_privdata(struct ata_port *ap);
64 void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
65 u32 opts);
66 void ahci_save_initial_config(struct device *dev,
e8791d4f
AM
67diff -urNp -x '*.orig' linux-4.9/drivers/ata/libahci.c linux-4.9/drivers/ata/libahci.c
68--- linux-4.9/drivers/ata/libahci.c 2021-02-24 16:29:54.606714867 +0100
69+++ linux-4.9/drivers/ata/libahci.c 2021-02-24 16:30:09.263850192 +0100
70@@ -743,6 +743,7 @@ static int ahci_set_lpm(struct ata_link
71 {
72 struct ata_port *ap = link->ap;
73 struct ahci_host_priv *hpriv = ap->host->private_data;
74+ struct ahci_port_priv *ppriv = ap->private_data;
75 struct ahci_port_priv *pp = ap->private_data;
76 void __iomem *port_mmio = ahci_port_base(ap);
77
78@@ -763,10 +764,10 @@ static int ahci_set_lpm(struct ata_link
79
80 if (hpriv->cap & HOST_CAP_ALPM) {
81 u32 cmd = readl(port_mmio + PORT_CMD);
82+ if (!(hints & ATA_LPM_WAKE_ONLY))
83+ cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
84
85 if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
86- if (!(hints & ATA_LPM_WAKE_ONLY))
87- cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
88 cmd |= PORT_CMD_ICC_ACTIVE;
89
90 writel(cmd, port_mmio + PORT_CMD);
91@@ -777,6 +778,13 @@ static int ahci_set_lpm(struct ata_link
92
93 if (hints & ATA_LPM_WAKE_ONLY)
94 return 0;
95+ } else if (policy == ATA_LPM_FIRMWARE_DEFAULTS) {
96+ if (ppriv->init_alpe)
97+ cmd |= PORT_CMD_ALPE;
98+ if (ppriv->init_asp)
99+ cmd |= PORT_CMD_ASP;
100+
101+ writel(cmd, port_mmio + PORT_CMD);
102 } else {
103 cmd |= PORT_CMD_ALPE;
104 if (policy == ATA_LPM_MIN_POWER)
105@@ -791,10 +799,18 @@ static int ahci_set_lpm(struct ata_link
106 if ((hpriv->cap2 & HOST_CAP2_SDS) &&
107 (hpriv->cap2 & HOST_CAP2_SADM) &&
108 (link->device->flags & ATA_DFLAG_DEVSLP)) {
109- if (policy == ATA_LPM_MIN_POWER)
110+ switch (policy) {
111+ case ATA_LPM_MIN_POWER:
112 ahci_set_aggressive_devslp(ap, true);
113- else
114+ break;
115+ case ATA_LPM_FIRMWARE_DEFAULTS:
116+ case ATA_LPM_MED_POWER:
117+ ahci_set_aggressive_devslp(ap, ppriv->init_devslp);
118+ break;
119+ default:
120 ahci_set_aggressive_devslp(ap, false);
121+ break;
122+ }
123 }
124
125 if (policy == ATA_LPM_MAX_POWER) {
126@@ -2076,6 +2092,7 @@ static void ahci_post_internal_cmd(struc
127 static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
128 {
129 struct ahci_host_priv *hpriv = ap->host->private_data;
130+ struct ahci_port_priv *ppriv = ap->private_data;
131 void __iomem *port_mmio = ahci_port_base(ap);
132 struct ata_device *dev = ap->link.device;
133 u32 devslp, dm, dito, mdat, deto;
134@@ -2111,26 +2128,32 @@ static void ahci_set_aggressive_devslp(s
135 if (rc)
136 return;
137
138- dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
139- dito = devslp_idle_timeout / (dm + 1);
140- if (dito > 0x3ff)
141- dito = 0x3ff;
142-
143- /* Use the nominal value 10 ms if the read MDAT is zero,
144- * the nominal value of DETO is 20 ms.
145- */
146- if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
147- ATA_LOG_DEVSLP_VALID_MASK) {
148- mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
149- ATA_LOG_DEVSLP_MDAT_MASK;
150- if (!mdat)
151+ if (ppriv->init_devslp) {
152+ dito = ppriv->init_dito;
153+ deto = ppriv->init_deto;
154+ mdat = ppriv->init_mdat;
155+ } else {
156+ dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
157+ dito = devslp_idle_timeout / (dm + 1);
158+ if (dito > 0x3ff)
159+ dito = 0x3ff;
160+
161+ /* Use the nominal value 10 ms if the read MDAT is zero,
162+ * the nominal value of DETO is 20 ms.
163+ */
164+ if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
165+ ATA_LOG_DEVSLP_VALID_MASK) {
166+ mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
167+ ATA_LOG_DEVSLP_MDAT_MASK;
168+ if (!mdat)
169+ mdat = 10;
170+ deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
171+ if (!deto)
172+ deto = 20;
173+ } else {
174 mdat = 10;
175- deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
176- if (!deto)
177 deto = 20;
178- } else {
179- mdat = 10;
180- deto = 20;
181+ }
182 }
183
184 /* Make dito, mdat, deto bits to 0s */
185@@ -2298,19 +2321,53 @@ static int ahci_port_suspend(struct ata_
2155c5a2
JR
186 }
187 #endif
188
189+/*
190+ * Allocate port privdata and read back initial power management configuration
191+ */
192+int ahci_setup_port_privdata(struct ata_port *ap)
193+{
194+ struct ahci_port_priv *pp;
195+ u32 cmd, devslp;
196+ void __iomem *port_mmio = ahci_port_base(ap);
197+
198+ pp = kzalloc(sizeof(*pp), GFP_KERNEL);
199+ if (!pp)
200+ return -ENOMEM;
201+
202+ ap->private_data = pp;
203+
204+ cmd = readl(port_mmio + PORT_CMD);
205+
206+ if (cmd & PORT_CMD_ALPE)
207+ pp->init_alpe = true;
208+
209+ if (cmd & PORT_CMD_ASP)
210+ pp->init_asp = true;
211+
212+ devslp = readl(port_mmio + PORT_DEVSLP);
213+
214+ /* devslp unsupported or disabled */
215+ if (!(devslp & PORT_DEVSLP_DSP) || !(devslp & PORT_DEVSLP_ADSE))
216+ return 0;
217+
218+ pp->init_devslp = true;
219+ pp->init_dito = (devslp >> PORT_DEVSLP_DITO_OFFSET) & 0x3ff;
220+ pp->init_deto = (devslp >> PORT_DEVSLP_DETO_OFFSET) & 0xff;
221+ pp->init_mdat = (devslp >> PORT_DEVSLP_MDAT_OFFSET) & 0x1f;
222+
223+ return 0;
224+}
225+EXPORT_SYMBOL_GPL(ahci_setup_port_privdata);
226+
227 static int ahci_port_start(struct ata_port *ap)
228 {
229 struct ahci_host_priv *hpriv = ap->host->private_data;
230+ struct ahci_port_priv *pp = ap->private_data;
231 struct device *dev = ap->host->dev;
232- struct ahci_port_priv *pp;
233 void *mem;
234 dma_addr_t mem_dma;
235 size_t dma_sz, rx_fis_sz;
236
237- pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
238- if (!pp)
239- return -ENOMEM;
240-
241 if (ap->host->n_ports > 1) {
242 pp->irq_desc = devm_kzalloc(dev, 8, GFP_KERNEL);
243 if (!pp->irq_desc) {
e8791d4f 244@@ -2389,8 +2446,6 @@ static int ahci_port_start(struct ata_po
2155c5a2
JR
245 ap->lock = &pp->lock;
246 }
247
248- ap->private_data = pp;
249-
250 /* engage engines, captain */
251 return ahci_port_resume(ap);
252 }
e8791d4f
AM
253diff -urNp -x '*.orig' linux-4.9/drivers/ata/libahci_platform.c linux-4.9/drivers/ata/libahci_platform.c
254--- linux-4.9/drivers/ata/libahci_platform.c 2021-02-24 16:29:54.606714867 +0100
255+++ linux-4.9/drivers/ata/libahci_platform.c 2021-02-24 16:30:09.257183312 +0100
256@@ -571,6 +571,10 @@ int ahci_platform_init_host(struct platf
2155c5a2
JR
257 if (ap->flags & ATA_FLAG_EM)
258 ap->em_message_type = hpriv->em_msg_type;
259
260+ rc = ahci_setup_port_privdata(ap);
261+ if (rc)
262+ return rc;
263+
264 /* disabled/not-implemented port */
265 if (!(hpriv->port_map & (1 << i)))
266 ap->ops = &ata_dummy_port_ops;
e8791d4f
AM
267diff -urNp -x '*.orig' linux-4.9/drivers/ata/libata-core.c linux-4.9/drivers/ata/libata-core.c
268--- linux-4.9/drivers/ata/libata-core.c 2021-02-24 16:29:54.610048307 +0100
269+++ linux-4.9/drivers/ata/libata-core.c 2021-02-24 16:30:09.263850192 +0100
270@@ -2028,6 +2028,9 @@ retry:
2155c5a2
JR
271 }
272 }
273
e8791d4f 274+ if (id[79] & (1 << SATA_DIPM))
2155c5a2
JR
275+ dev->init_dipm = true;
276+
277 *p_class = class;
278
279 return 0;
e8791d4f
AM
280@@ -3835,6 +3838,11 @@ int sata_link_scr_lpm(struct ata_link *l
281 return rc;
282
283 switch (policy) {
284+ case ATA_LPM_FIRMWARE_DEFAULTS:
285+ /* use the values we read at probe */
286+ scontrol &= ~(0x7 << 8);
287+ scontrol |= (link->init_lpm << 8);
288+ break;
289 case ATA_LPM_MAX_POWER:
290 /* disable all LPM transitions */
291 scontrol |= (0x7 << 8);
292@@ -3845,10 +3853,6 @@ int sata_link_scr_lpm(struct ata_link *l
293 }
294 break;
295 case ATA_LPM_MED_POWER:
296- /* allow LPM to PARTIAL */
297- scontrol &= ~(0x1 << 8);
298- scontrol |= (0x6 << 8);
299- break;
300 case ATA_LPM_MIN_POWER:
301 if (ata_link_nr_enabled(link) > 0)
302 /* no restrictions on LPM transitions */
303@@ -5814,11 +5818,11 @@ void ata_link_init(struct ata_port *ap,
2155c5a2
JR
304 }
305
306 /**
307- * sata_link_init_spd - Initialize link->sata_spd_limit
308- * @link: Link to configure sata_spd_limit for
309+ * sata_link_init_config - Initialize link->sata_spd_limit and init_lpm
310+ * @link: Link to configure sata_spd_limit and init_lpm for
311 *
312- * Initialize @link->[hw_]sata_spd_limit to the currently
313- * configured value.
314+ * Initialize @link->[hw_]sata_spd_limit and @link->init_lpm to the
315+ * currently configured value.
316 *
317 * LOCKING:
318 * Kernel thread context (may sleep).
e8791d4f 319@@ -5826,7 +5830,7 @@ void ata_link_init(struct ata_port *ap,
2155c5a2
JR
320 * RETURNS:
321 * 0 on success, -errno on failure.
322 */
323-int sata_link_init_spd(struct ata_link *link)
324+int sata_link_init_config(struct ata_link *link)
325 {
326 u8 spd;
327 int rc;
e8791d4f 328@@ -5843,6 +5847,8 @@ int sata_link_init_spd(struct ata_link *
2155c5a2
JR
329
330 link->sata_spd_limit = link->hw_sata_spd_limit;
331
332+ link->init_lpm = (link->saved_scontrol >> 8) & 0x7;
333+
334 return 0;
335 }
336
e8791d4f 337@@ -6392,9 +6398,9 @@ int ata_host_register(struct ata_host *h
2155c5a2
JR
338 ap->cbl = ATA_CBL_SATA;
339
340 /* init sata_spd_limit to the current value */
341- sata_link_init_spd(&ap->link);
342+ sata_link_init_config(&ap->link);
343 if (ap->slave_link)
344- sata_link_init_spd(ap->slave_link);
345+ sata_link_init_config(ap->slave_link);
346
347 /* print per-port info to dmesg */
348 xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
e8791d4f
AM
349diff -urNp -x '*.orig' linux-4.9/drivers/ata/libata-eh.c linux-4.9/drivers/ata/libata-eh.c
350--- linux-4.9/drivers/ata/libata-eh.c 2021-02-24 16:29:54.610048307 +0100
351+++ linux-4.9/drivers/ata/libata-eh.c 2021-02-24 16:30:09.267183632 +0100
352@@ -3534,9 +3534,7 @@ static int ata_eh_set_lpm(struct ata_lin
353 return 0;
354
355 /*
356- * DIPM is enabled only for MIN_POWER as some devices
357- * misbehave when the host NACKs transition to SLUMBER. Order
358- * device and link configurations such that the host always
359+ * Order device and link configurations such that the host always
360 * allows DIPM requests.
361 */
362 ata_for_each_dev(dev, link, ENABLED) {
363@@ -3555,7 +3553,7 @@ static int ata_eh_set_lpm(struct ata_lin
364 hints &= ~ATA_LPM_HIPM;
365
366 /* disable DIPM before changing link config */
367- if (policy != ATA_LPM_MIN_POWER && dipm) {
368+ if (policy < ATA_LPM_MED_POWER && dipm) {
369 err_mask = ata_dev_set_feature(dev,
370 SETFEATURES_SATA_DISABLE, SATA_DIPM);
371 if (err_mask && err_mask != AC_ERR_DEV) {
372@@ -3596,10 +3594,13 @@ static int ata_eh_set_lpm(struct ata_lin
373 if (ap && ap->slave_link)
374 ap->slave_link->lpm_policy = policy;
375
376- /* host config updated, enable DIPM if transitioning to MIN_POWER */
377+ /* host config updated, enable DIPM if transitioning to MED_POWER,
378+ * MIN_POWER or FIRMWARE_DEFAULT when enabled by firmware
379+ */
380 ata_for_each_dev(dev, link, ENABLED) {
381- if (policy == ATA_LPM_MIN_POWER && !no_dipm &&
382- ata_id_has_dipm(dev->id)) {
383+ if ((policy >= ATA_LPM_MED_POWER && !no_dipm &&
384+ ata_id_has_dipm(dev->id)) ||
385+ (policy == ATA_LPM_FIRMWARE_DEFAULTS && dev->init_dipm)) {
386 err_mask = ata_dev_set_feature(dev,
387 SETFEATURES_SATA_ENABLE, SATA_DIPM);
388 if (err_mask && err_mask != AC_ERR_DEV) {
389diff -urNp -x '*.orig' linux-4.9/drivers/ata/libata-pmp.c linux-4.9/drivers/ata/libata-pmp.c
390--- linux-4.9/drivers/ata/libata-pmp.c 2021-02-24 16:29:54.610048307 +0100
391+++ linux-4.9/drivers/ata/libata-pmp.c 2021-02-24 16:30:09.260516752 +0100
392@@ -538,7 +538,7 @@ int sata_pmp_attach(struct ata_device *d
2155c5a2
JR
393 ap->ops->pmp_attach(ap);
394
395 ata_for_each_link(tlink, ap, EDGE)
396- sata_link_init_spd(tlink);
397+ sata_link_init_config(tlink);
398
399 return 0;
400
e8791d4f
AM
401diff -urNp -x '*.orig' linux-4.9/drivers/ata/libata-scsi.c linux-4.9/drivers/ata/libata-scsi.c
402--- linux-4.9/drivers/ata/libata-scsi.c 2021-02-24 16:29:54.610048307 +0100
403+++ linux-4.9/drivers/ata/libata-scsi.c 2021-02-24 16:30:09.263850192 +0100
404@@ -107,6 +107,7 @@ static const u8 def_control_mpage[CONTRO
405 static const char *ata_lpm_policy_names[] = {
406 [ATA_LPM_UNKNOWN] = "max_performance",
407 [ATA_LPM_MAX_POWER] = "max_performance",
408+ [ATA_LPM_FIRMWARE_DEFAULTS] = "firmware_defaults",
409 [ATA_LPM_MED_POWER] = "medium_power",
410 [ATA_LPM_MIN_POWER] = "min_power",
411 };
412diff -urNp -x '*.orig' linux-4.9/drivers/ata/libata.h linux-4.9/drivers/ata/libata.h
413--- linux-4.9/drivers/ata/libata.h 2016-12-11 20:17:54.000000000 +0100
414+++ linux-4.9/drivers/ata/libata.h 2021-02-24 16:30:09.260516752 +0100
415@@ -99,7 +99,7 @@ extern bool ata_phys_link_online(struct
2155c5a2
JR
416 extern bool ata_phys_link_offline(struct ata_link *link);
417 extern void ata_dev_init(struct ata_device *dev);
418 extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp);
419-extern int sata_link_init_spd(struct ata_link *link);
420+extern int sata_link_init_config(struct ata_link *link);
421 extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
422 extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
423 extern struct ata_port *ata_port_alloc(struct ata_host *host);
e8791d4f
AM
424diff -urNp -x '*.orig' linux-4.9/drivers/ata/sata_highbank.c linux-4.9/drivers/ata/sata_highbank.c
425--- linux-4.9/drivers/ata/sata_highbank.c 2016-12-11 20:17:54.000000000 +0100
426+++ linux-4.9/drivers/ata/sata_highbank.c 2021-02-24 16:30:09.260516752 +0100
427@@ -557,6 +557,10 @@ static int ahci_highbank_probe(struct pl
2155c5a2
JR
428 if (ap->flags & ATA_FLAG_EM)
429 ap->em_message_type = hpriv->em_msg_type;
430
431+ rc = ahci_setup_port_privdata(ap);
432+ if (rc)
433+ goto err0;
434+
435 /* disabled/not-implemented port */
436 if (!(hpriv->port_map & (1 << i)))
437 ap->ops = &ata_dummy_port_ops;
e8791d4f
AM
438diff -urNp -x '*.orig' linux-4.9/include/linux/libata.h linux-4.9/include/linux/libata.h
439--- linux-4.9/include/linux/libata.h 2021-02-24 16:29:56.030093715 +0100
440+++ linux-4.9/include/linux/libata.h 2021-02-24 16:30:09.263850192 +0100
441@@ -520,6 +520,7 @@ enum ata_completion_errors {
442 enum ata_lpm_policy {
443 ATA_LPM_UNKNOWN,
444 ATA_LPM_MAX_POWER,
445+ ATA_LPM_FIRMWARE_DEFAULTS,
446 ATA_LPM_MED_POWER,
447 ATA_LPM_MIN_POWER,
448 };
449@@ -740,6 +741,8 @@ struct ata_device {
2155c5a2
JR
450 int spdn_cnt;
451 /* ering is CLEAR_END, read comment above CLEAR_END */
452 struct ata_ering ering;
453+ /* Initial DIPM configuration */
454+ bool init_dipm;
455 };
456
457 /* Fields between ATA_DEVICE_CLEAR_BEGIN and ATA_DEVICE_CLEAR_END are
e8791d4f 458@@ -811,6 +814,7 @@ struct ata_link {
2155c5a2 459 struct ata_device device[ATA_MAX_DEVICES];
b912730e
AM
460
461 unsigned long last_lpm_change; /* when last LPM change happened */
2155c5a2
JR
462+ u8 init_lpm; /* initial lpm configuration */
463 };
464 #define ATA_LINK_CLEAR_BEGIN offsetof(struct ata_link, active_tag)
465 #define ATA_LINK_CLEAR_END offsetof(struct ata_link, device[0])
This page took 0.121071 seconds and 4 git commands to generate.