]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-libata-ahci-pm.patch
- 4.4.274
[packages/kernel.git] / kernel-libata-ahci-pm.patch
CommitLineData
c2806d43
AM
1diff -urNp -x '*.orig' linux-4.4/Documentation/scsi/link_power_management_policy.txt linux-4.4/Documentation/scsi/link_power_management_policy.txt
2--- linux-4.4/Documentation/scsi/link_power_management_policy.txt 2016-01-11 00:01:32.000000000 +0100
3+++ linux-4.4/Documentation/scsi/link_power_management_policy.txt 2021-02-24 17:42:47.900118751 +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.4/drivers/ata/acard-ahci.c linux-4.4/drivers/ata/acard-ahci.c
18--- linux-4.4/drivers/ata/acard-ahci.c 2021-02-24 17:42:34.233049827 +0100
19+++ linux-4.4/drivers/ata/acard-ahci.c 2021-02-24 17:42:47.896785319 +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;
c2806d43
AM
30diff -urNp -x '*.orig' linux-4.4/drivers/ata/ahci.c linux-4.4/drivers/ata/ahci.c
31--- linux-4.4/drivers/ata/ahci.c 2021-02-24 17:42:34.233049827 +0100
32+++ linux-4.4/drivers/ata/ahci.c 2021-02-24 17:42:47.896785319 +0100
33@@ -1695,6 +1695,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)))
c2806d43
AM
43diff -urNp -x '*.orig' linux-4.4/drivers/ata/ahci.h linux-4.4/drivers/ata/ahci.h
44--- linux-4.4/drivers/ata/ahci.h 2016-01-11 00:01:32.000000000 +0100
45+++ linux-4.4/drivers/ata/ahci.h 2021-02-24 17:42:47.896785319 +0100
46@@ -317,6 +317,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 {
c2806d43 59@@ -376,6 +382,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,
c2806d43
AM
67diff -urNp -x '*.orig' linux-4.4/drivers/ata/libahci.c linux-4.4/drivers/ata/libahci.c
68--- linux-4.4/drivers/ata/libahci.c 2021-02-24 17:42:34.233049827 +0100
69+++ linux-4.4/drivers/ata/libahci.c 2021-02-24 17:42:47.903452182 +0100
70@@ -684,6 +684,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@@ -701,9 +702,9 @@ 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+ cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
83
84 if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
85- cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
86 cmd |= PORT_CMD_ICC_ACTIVE;
87
88 writel(cmd, port_mmio + PORT_CMD);
89@@ -711,6 +712,13 @@ static int ahci_set_lpm(struct ata_link
90
91 /* wait 10ms to be sure we've come out of LPM state */
92 ata_msleep(ap, 10);
93+ } else if (policy == ATA_LPM_FIRMWARE_DEFAULTS) {
94+ if (ppriv->init_alpe)
95+ cmd |= PORT_CMD_ALPE;
96+ if (ppriv->init_asp)
97+ cmd |= PORT_CMD_ASP;
98+
99+ writel(cmd, port_mmio + PORT_CMD);
100 } else {
101 cmd |= PORT_CMD_ALPE;
102 if (policy == ATA_LPM_MIN_POWER)
103@@ -725,10 +733,18 @@ static int ahci_set_lpm(struct ata_link
104 if ((hpriv->cap2 & HOST_CAP2_SDS) &&
105 (hpriv->cap2 & HOST_CAP2_SADM) &&
106 (link->device->flags & ATA_DFLAG_DEVSLP)) {
107- if (policy == ATA_LPM_MIN_POWER)
108+ switch (policy) {
109+ case ATA_LPM_MIN_POWER:
110 ahci_set_aggressive_devslp(ap, true);
111- else
112+ break;
113+ case ATA_LPM_FIRMWARE_DEFAULTS:
114+ case ATA_LPM_MED_POWER:
115+ ahci_set_aggressive_devslp(ap, ppriv->init_devslp);
116+ break;
117+ default:
118 ahci_set_aggressive_devslp(ap, false);
119+ break;
120+ }
121 }
122
123 if (policy == ATA_LPM_MAX_POWER) {
124@@ -2057,6 +2073,7 @@ static void ahci_post_internal_cmd(struc
125 static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
126 {
127 struct ahci_host_priv *hpriv = ap->host->private_data;
128+ struct ahci_port_priv *ppriv = ap->private_data;
129 void __iomem *port_mmio = ahci_port_base(ap);
130 struct ata_device *dev = ap->link.device;
131 u32 devslp, dm, dito, mdat, deto;
132@@ -2092,26 +2109,32 @@ static void ahci_set_aggressive_devslp(s
133 if (rc)
134 return;
135
136- dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
137- dito = devslp_idle_timeout / (dm + 1);
138- if (dito > 0x3ff)
139- dito = 0x3ff;
140-
141- /* Use the nominal value 10 ms if the read MDAT is zero,
142- * the nominal value of DETO is 20 ms.
143- */
144- if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
145- ATA_LOG_DEVSLP_VALID_MASK) {
146- mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
147- ATA_LOG_DEVSLP_MDAT_MASK;
148- if (!mdat)
149+ if (ppriv->init_devslp) {
150+ dito = ppriv->init_dito;
151+ deto = ppriv->init_deto;
152+ mdat = ppriv->init_mdat;
153+ } else {
154+ dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
155+ dito = devslp_idle_timeout / (dm + 1);
156+ if (dito > 0x3ff)
157+ dito = 0x3ff;
158+
159+ /* Use the nominal value 10 ms if the read MDAT is zero,
160+ * the nominal value of DETO is 20 ms.
161+ */
162+ if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
163+ ATA_LOG_DEVSLP_VALID_MASK) {
164+ mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
165+ ATA_LOG_DEVSLP_MDAT_MASK;
166+ if (!mdat)
167+ mdat = 10;
168+ deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
169+ if (!deto)
170+ deto = 20;
171+ } else {
172 mdat = 10;
173- deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
174- if (!deto)
175 deto = 20;
176- } else {
177- mdat = 10;
178- deto = 20;
179+ }
180 }
181
182 /* Make dito, mdat, deto bits to 0s */
183@@ -2276,19 +2299,53 @@ static int ahci_port_suspend(struct ata_
2155c5a2
JR
184 }
185 #endif
186
187+/*
188+ * Allocate port privdata and read back initial power management configuration
189+ */
190+int ahci_setup_port_privdata(struct ata_port *ap)
191+{
192+ struct ahci_port_priv *pp;
193+ u32 cmd, devslp;
194+ void __iomem *port_mmio = ahci_port_base(ap);
195+
196+ pp = kzalloc(sizeof(*pp), GFP_KERNEL);
197+ if (!pp)
198+ return -ENOMEM;
199+
200+ ap->private_data = pp;
201+
202+ cmd = readl(port_mmio + PORT_CMD);
203+
204+ if (cmd & PORT_CMD_ALPE)
205+ pp->init_alpe = true;
206+
207+ if (cmd & PORT_CMD_ASP)
208+ pp->init_asp = true;
209+
210+ devslp = readl(port_mmio + PORT_DEVSLP);
211+
212+ /* devslp unsupported or disabled */
213+ if (!(devslp & PORT_DEVSLP_DSP) || !(devslp & PORT_DEVSLP_ADSE))
214+ return 0;
215+
216+ pp->init_devslp = true;
217+ pp->init_dito = (devslp >> PORT_DEVSLP_DITO_OFFSET) & 0x3ff;
218+ pp->init_deto = (devslp >> PORT_DEVSLP_DETO_OFFSET) & 0xff;
219+ pp->init_mdat = (devslp >> PORT_DEVSLP_MDAT_OFFSET) & 0x1f;
220+
221+ return 0;
222+}
223+EXPORT_SYMBOL_GPL(ahci_setup_port_privdata);
224+
225 static int ahci_port_start(struct ata_port *ap)
226 {
227 struct ahci_host_priv *hpriv = ap->host->private_data;
228+ struct ahci_port_priv *pp = ap->private_data;
229 struct device *dev = ap->host->dev;
230- struct ahci_port_priv *pp;
231 void *mem;
232 dma_addr_t mem_dma;
233 size_t dma_sz, rx_fis_sz;
234
235- pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
236- if (!pp)
237- return -ENOMEM;
238-
239 if (ap->host->n_ports > 1) {
240 pp->irq_desc = devm_kzalloc(dev, 8, GFP_KERNEL);
241 if (!pp->irq_desc) {
c2806d43 242@@ -2367,8 +2424,6 @@ static int ahci_port_start(struct ata_po
2155c5a2
JR
243 ap->lock = &pp->lock;
244 }
245
246- ap->private_data = pp;
247-
248 /* engage engines, captain */
249 return ahci_port_resume(ap);
250 }
c2806d43
AM
251diff -urNp -x '*.orig' linux-4.4/drivers/ata/libahci_platform.c linux-4.4/drivers/ata/libahci_platform.c
252--- linux-4.4/drivers/ata/libahci_platform.c 2021-02-24 17:42:34.233049827 +0100
253+++ linux-4.4/drivers/ata/libahci_platform.c 2021-02-24 17:42:47.896785319 +0100
254@@ -569,6 +569,10 @@ int ahci_platform_init_host(struct platf
2155c5a2
JR
255 if (ap->flags & ATA_FLAG_EM)
256 ap->em_message_type = hpriv->em_msg_type;
257
258+ rc = ahci_setup_port_privdata(ap);
259+ if (rc)
260+ return rc;
261+
262 /* disabled/not-implemented port */
263 if (!(hpriv->port_map & (1 << i)))
264 ap->ops = &ata_dummy_port_ops;
c2806d43
AM
265diff -urNp -x '*.orig' linux-4.4/drivers/ata/libata-core.c linux-4.4/drivers/ata/libata-core.c
266--- linux-4.4/drivers/ata/libata-core.c 2021-02-24 17:42:34.233049827 +0100
267+++ linux-4.4/drivers/ata/libata-core.c 2021-02-24 17:42:47.903452182 +0100
268@@ -2023,6 +2023,9 @@ retry:
2155c5a2
JR
269 }
270 }
271
c2806d43 272+ if (id[79] & (1 << SATA_DIPM))
2155c5a2
JR
273+ dev->init_dipm = true;
274+
275 *p_class = class;
276
277 return 0;
c2806d43
AM
278@@ -3657,6 +3660,11 @@ int sata_link_scr_lpm(struct ata_link *l
279 return rc;
280
281 switch (policy) {
282+ case ATA_LPM_FIRMWARE_DEFAULTS:
283+ /* use the values we read at probe */
284+ scontrol &= ~(0x7 << 8);
285+ scontrol |= (link->init_lpm << 8);
286+ break;
287 case ATA_LPM_MAX_POWER:
288 /* disable all LPM transitions */
289 scontrol |= (0x7 << 8);
290@@ -3667,10 +3675,6 @@ int sata_link_scr_lpm(struct ata_link *l
291 }
292 break;
293 case ATA_LPM_MED_POWER:
294- /* allow LPM to PARTIAL */
295- scontrol &= ~(0x1 << 8);
296- scontrol |= (0x6 << 8);
297- break;
298 case ATA_LPM_MIN_POWER:
299 if (ata_link_nr_enabled(link) > 0)
300 /* no restrictions on LPM transitions */
301@@ -5627,11 +5631,11 @@ void ata_link_init(struct ata_port *ap,
2155c5a2
JR
302 }
303
304 /**
305- * sata_link_init_spd - Initialize link->sata_spd_limit
306- * @link: Link to configure sata_spd_limit for
307+ * sata_link_init_config - Initialize link->sata_spd_limit and init_lpm
308+ * @link: Link to configure sata_spd_limit and init_lpm for
309 *
310- * Initialize @link->[hw_]sata_spd_limit to the currently
311- * configured value.
312+ * Initialize @link->[hw_]sata_spd_limit and @link->init_lpm to the
313+ * currently configured value.
314 *
315 * LOCKING:
316 * Kernel thread context (may sleep).
c2806d43 317@@ -5639,7 +5643,7 @@ void ata_link_init(struct ata_port *ap,
2155c5a2
JR
318 * RETURNS:
319 * 0 on success, -errno on failure.
320 */
321-int sata_link_init_spd(struct ata_link *link)
322+int sata_link_init_config(struct ata_link *link)
323 {
324 u8 spd;
325 int rc;
c2806d43 326@@ -5656,6 +5660,8 @@ int sata_link_init_spd(struct ata_link *
2155c5a2
JR
327
328 link->sata_spd_limit = link->hw_sata_spd_limit;
329
330+ link->init_lpm = (link->saved_scontrol >> 8) & 0x7;
331+
332 return 0;
333 }
334
c2806d43 335@@ -6205,9 +6211,9 @@ int ata_host_register(struct ata_host *h
2155c5a2
JR
336 ap->cbl = ATA_CBL_SATA;
337
338 /* init sata_spd_limit to the current value */
339- sata_link_init_spd(&ap->link);
340+ sata_link_init_config(&ap->link);
341 if (ap->slave_link)
342- sata_link_init_spd(ap->slave_link);
343+ sata_link_init_config(ap->slave_link);
344
345 /* print per-port info to dmesg */
346 xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
c2806d43
AM
347diff -urNp -x '*.orig' linux-4.4/drivers/ata/libata-eh.c linux-4.4/drivers/ata/libata-eh.c
348--- linux-4.4/drivers/ata/libata-eh.c 2021-02-24 17:42:34.236383257 +0100
349+++ linux-4.4/drivers/ata/libata-eh.c 2021-02-24 17:42:47.906785614 +0100
350@@ -3441,9 +3441,7 @@ static int ata_eh_set_lpm(struct ata_lin
351 return 0;
352
353 /*
354- * DIPM is enabled only for MIN_POWER as some devices
355- * misbehave when the host NACKs transition to SLUMBER. Order
356- * device and link configurations such that the host always
357+ * Order device and link configurations such that the host always
358 * allows DIPM requests.
359 */
360 ata_for_each_dev(dev, link, ENABLED) {
361@@ -3462,7 +3460,7 @@ static int ata_eh_set_lpm(struct ata_lin
362 hints &= ~ATA_LPM_HIPM;
363
364 /* disable DIPM before changing link config */
365- if (policy != ATA_LPM_MIN_POWER && dipm) {
366+ if (policy < ATA_LPM_MED_POWER && dipm) {
367 err_mask = ata_dev_set_feature(dev,
368 SETFEATURES_SATA_DISABLE, SATA_DIPM);
369 if (err_mask && err_mask != AC_ERR_DEV) {
370@@ -3503,10 +3501,13 @@ static int ata_eh_set_lpm(struct ata_lin
371 if (ap && ap->slave_link)
372 ap->slave_link->lpm_policy = policy;
373
374- /* host config updated, enable DIPM if transitioning to MIN_POWER */
375+ /* host config updated, enable DIPM if transitioning to MED_POWER,
376+ * MIN_POWER or FIRMWARE_DEFAULT when enabled by firmware
377+ */
378 ata_for_each_dev(dev, link, ENABLED) {
379- if (policy == ATA_LPM_MIN_POWER && !no_dipm &&
380- ata_id_has_dipm(dev->id)) {
381+ if ((policy >= ATA_LPM_MED_POWER && !no_dipm &&
382+ ata_id_has_dipm(dev->id)) ||
383+ (policy == ATA_LPM_FIRMWARE_DEFAULTS && dev->init_dipm)) {
384 err_mask = ata_dev_set_feature(dev,
385 SETFEATURES_SATA_ENABLE, SATA_DIPM);
386 if (err_mask && err_mask != AC_ERR_DEV) {
387diff -urNp -x '*.orig' linux-4.4/drivers/ata/libata-pmp.c linux-4.4/drivers/ata/libata-pmp.c
388--- linux-4.4/drivers/ata/libata-pmp.c 2021-02-24 17:42:34.236383257 +0100
389+++ linux-4.4/drivers/ata/libata-pmp.c 2021-02-24 17:42:47.900118751 +0100
390@@ -538,7 +538,7 @@ int sata_pmp_attach(struct ata_device *d
2155c5a2
JR
391 ap->ops->pmp_attach(ap);
392
393 ata_for_each_link(tlink, ap, EDGE)
394- sata_link_init_spd(tlink);
395+ sata_link_init_config(tlink);
396
397 return 0;
398
c2806d43
AM
399diff -urNp -x '*.orig' linux-4.4/drivers/ata/libata-scsi.c linux-4.4/drivers/ata/libata-scsi.c
400--- linux-4.4/drivers/ata/libata-scsi.c 2021-02-24 17:42:34.236383257 +0100
401+++ linux-4.4/drivers/ata/libata-scsi.c 2021-02-24 17:42:47.903452182 +0100
402@@ -107,6 +107,7 @@ static const u8 def_control_mpage[CONTRO
403 static const char *ata_lpm_policy_names[] = {
404 [ATA_LPM_UNKNOWN] = "max_performance",
405 [ATA_LPM_MAX_POWER] = "max_performance",
406+ [ATA_LPM_FIRMWARE_DEFAULTS] = "firmware_defaults",
407 [ATA_LPM_MED_POWER] = "medium_power",
408 [ATA_LPM_MIN_POWER] = "min_power",
409 };
410diff -urNp -x '*.orig' linux-4.4/drivers/ata/libata.h linux-4.4/drivers/ata/libata.h
411--- linux-4.4/drivers/ata/libata.h 2016-01-11 00:01:32.000000000 +0100
412+++ linux-4.4/drivers/ata/libata.h 2021-02-24 17:42:47.900118751 +0100
413@@ -98,7 +98,7 @@ extern bool ata_phys_link_online(struct
2155c5a2
JR
414 extern bool ata_phys_link_offline(struct ata_link *link);
415 extern void ata_dev_init(struct ata_device *dev);
416 extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp);
417-extern int sata_link_init_spd(struct ata_link *link);
418+extern int sata_link_init_config(struct ata_link *link);
419 extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
420 extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
421 extern struct ata_port *ata_port_alloc(struct ata_host *host);
c2806d43
AM
422diff -urNp -x '*.orig' linux-4.4/drivers/ata/sata_highbank.c linux-4.4/drivers/ata/sata_highbank.c
423--- linux-4.4/drivers/ata/sata_highbank.c 2016-01-11 00:01:32.000000000 +0100
424+++ linux-4.4/drivers/ata/sata_highbank.c 2021-02-24 17:42:47.900118751 +0100
425@@ -557,6 +557,10 @@ static int ahci_highbank_probe(struct pl
2155c5a2
JR
426 if (ap->flags & ATA_FLAG_EM)
427 ap->em_message_type = hpriv->em_msg_type;
428
429+ rc = ahci_setup_port_privdata(ap);
430+ if (rc)
431+ goto err0;
432+
433 /* disabled/not-implemented port */
434 if (!(hpriv->port_map & (1 << i)))
435 ap->ops = &ata_dummy_port_ops;
c2806d43
AM
436diff -urNp -x '*.orig' linux-4.4/include/linux/libata.h linux-4.4/include/linux/libata.h
437--- linux-4.4/include/linux/libata.h 2021-02-24 17:42:35.659758447 +0100
438+++ linux-4.4/include/linux/libata.h 2021-02-24 17:42:47.903452182 +0100
439@@ -521,6 +521,7 @@ enum ata_completion_errors {
440 enum ata_lpm_policy {
441 ATA_LPM_UNKNOWN,
442 ATA_LPM_MAX_POWER,
443+ ATA_LPM_FIRMWARE_DEFAULTS,
444 ATA_LPM_MED_POWER,
445 ATA_LPM_MIN_POWER,
446 };
447@@ -733,6 +734,8 @@ struct ata_device {
2155c5a2
JR
448 int spdn_cnt;
449 /* ering is CLEAR_END, read comment above CLEAR_END */
450 struct ata_ering ering;
451+ /* Initial DIPM configuration */
452+ bool init_dipm;
453 };
454
455 /* Fields between ATA_DEVICE_CLEAR_BEGIN and ATA_DEVICE_CLEAR_END are
c2806d43 456@@ -804,6 +807,7 @@ struct ata_link {
2155c5a2 457 struct ata_device device[ATA_MAX_DEVICES];
b912730e
AM
458
459 unsigned long last_lpm_change; /* when last LPM change happened */
2155c5a2
JR
460+ u8 init_lpm; /* initial lpm configuration */
461 };
462 #define ATA_LINK_CLEAR_BEGIN offsetof(struct ata_link, active_tag)
463 #define ATA_LINK_CLEAR_END offsetof(struct ata_link, device[0])
This page took 0.096066 seconds and 4 git commands to generate.