]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-libata-ahci-pm.patch
- up to 4.9.217
[packages/kernel.git] / kernel-libata-ahci-pm.patch
1 From:   Matthew Garrett <mjg59@coreos.com>
2 Date:   Sat, 18 Apr 2015 08:26:34 -0700
3 Subject: [PATCH 1/3] libata: Stash initial power management configuration
4
5 The initial configuration for power management settings may be a result of
6 the firmware using its knowledge of the installed hardware to program
7 reasonable defaults. Stash as much of it as possible for later use.
8
9 Signed-off-by: Matthew Garrett <mjg59@srcf.ucam.org>
10 ---
11  drivers/ata/acard-ahci.c       |  3 +++
12  drivers/ata/ahci.c             |  3 +++
13  drivers/ata/ahci.h             |  7 +++++++
14  drivers/ata/libahci.c          | 46 +++++++++++++++++++++++++++++++++++-------
15  drivers/ata/libahci_platform.c |  4 ++++
16  drivers/ata/libata-core.c      | 19 ++++++++++-------
17  drivers/ata/libata-pmp.c       |  2 +-
18  drivers/ata/libata.h           |  2 +-
19  drivers/ata/sata_highbank.c    |  4 ++++
20  include/linux/libata.h         |  3 +++
21  10 files changed, 77 insertions(+), 16 deletions(-)
22
23 diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c
24 index 12489ce..0029229 100644
25 --- a/drivers/ata/acard-ahci.c
26 +++ b/drivers/ata/acard-ahci.c
27 @@ -476,6 +476,9 @@ static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id
28                 ata_port_pbar_desc(ap, AHCI_PCI_BAR,
29                                    0x100 + ap->port_no * 0x80, "port");
30  
31 +               rc = ahci_setup_port_privdata(ap);
32 +               if (rc)
33 +                       return rc;
34                 /* set initial link pm policy */
35                 /*
36                 ap->pm_policy = NOT_AVAILABLE;
37 diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
38 index c7a92a7..0f875e2 100644
39 --- a/drivers/ata/ahci.c
40 +++ b/drivers/ata/ahci.c
41 @@ -1436,6 +1436,9 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
42                 if (ap->flags & ATA_FLAG_EM)
43                         ap->em_message_type = hpriv->em_msg_type;
44  
45 +               rc = ahci_setup_port_privdata(ap);
46 +               if (rc)
47 +                       return rc;
48  
49                 /* disabled/not-implemented port */
50                 if (!(hpriv->port_map & (1 << i)))
51 diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
52 index 71262e0..c1a4b6a 100644
53 --- a/drivers/ata/ahci.h
54 +++ b/drivers/ata/ahci.h
55 @@ -313,6 +313,12 @@ struct ahci_port_priv {
56         /* enclosure management info per PM slot */
57         struct ahci_em_priv     em_priv[EM_MAX_SLOTS];
58         char                    *irq_desc;      /* desc in /proc/interrupts */
59 +       bool                    init_alpe;      /* alpe enabled by default */
60 +       bool                    init_asp;       /* asp enabled by default */
61 +       bool                    init_devslp;    /* devslp enabled by default */
62 +       u32                     init_dito;      /* initial dito configuration */
63 +       u32                     init_deto;      /* initial deto configuration */
64 +       u32                     init_mdat;      /* initial mdat configuration */
65  };
66  
67  struct ahci_host_priv {
68 @@ -371,6 +377,7 @@ extern struct ata_port_operations ahci_platform_ops;
69  extern struct ata_port_operations ahci_pmp_retry_srst_ops;
70  
71  unsigned int ahci_dev_classify(struct ata_port *ap);
72 +int ahci_setup_port_privdata(struct ata_port *ap);
73  void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
74                         u32 opts);
75  void ahci_save_initial_config(struct device *dev,
76 diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
77 index 61a9c07..f0c7120 100644
78 --- a/drivers/ata/libahci.c
79 +++ b/drivers/ata/libahci.c
80 @@ -2212,19 +2212,53 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg)
81  }
82  #endif
83  
84 +/*
85 + * Allocate port privdata and read back initial power management configuration
86 + */
87 +int ahci_setup_port_privdata(struct ata_port *ap)
88 +{
89 +       struct ahci_port_priv *pp;
90 +       u32 cmd, devslp;
91 +       void __iomem *port_mmio = ahci_port_base(ap);
92 +
93 +       pp = kzalloc(sizeof(*pp), GFP_KERNEL);
94 +       if (!pp)
95 +               return -ENOMEM;
96 +
97 +       ap->private_data = pp;
98 +
99 +       cmd = readl(port_mmio + PORT_CMD);
100 +
101 +       if (cmd & PORT_CMD_ALPE)
102 +               pp->init_alpe = true;
103 +
104 +       if (cmd & PORT_CMD_ASP)
105 +               pp->init_asp = true;
106 +
107 +       devslp = readl(port_mmio + PORT_DEVSLP);
108 +
109 +       /* devslp unsupported or disabled */
110 +       if (!(devslp & PORT_DEVSLP_DSP) || !(devslp & PORT_DEVSLP_ADSE))
111 +               return 0;
112 +
113 +       pp->init_devslp = true;
114 +       pp->init_dito = (devslp >> PORT_DEVSLP_DITO_OFFSET) & 0x3ff;
115 +       pp->init_deto = (devslp >> PORT_DEVSLP_DETO_OFFSET) & 0xff;
116 +       pp->init_mdat = (devslp >> PORT_DEVSLP_MDAT_OFFSET) & 0x1f;
117 +
118 +       return 0;
119 +}
120 +EXPORT_SYMBOL_GPL(ahci_setup_port_privdata);
121 +
122  static int ahci_port_start(struct ata_port *ap)
123  {
124         struct ahci_host_priv *hpriv = ap->host->private_data;
125 +       struct ahci_port_priv *pp = ap->private_data;
126         struct device *dev = ap->host->dev;
127 -       struct ahci_port_priv *pp;
128         void *mem;
129         dma_addr_t mem_dma;
130         size_t dma_sz, rx_fis_sz;
131  
132 -       pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
133 -       if (!pp)
134 -               return -ENOMEM;
135 -
136         if (ap->host->n_ports > 1) {
137                 pp->irq_desc = devm_kzalloc(dev, 8, GFP_KERNEL);
138                 if (!pp->irq_desc) {
139 @@ -2303,8 +2337,6 @@ static int ahci_port_start(struct ata_port *ap)
140                 ap->lock = &pp->lock;
141         }
142  
143 -       ap->private_data = pp;
144 -
145         /* engage engines, captain */
146         return ahci_port_resume(ap);
147  }
148 diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c
149 index d89305d..39946d4 100644
150 --- a/drivers/ata/libahci_platform.c
151 +++ b/drivers/ata/libahci_platform.c
152 @@ -563,6 +563,10 @@ int ahci_platform_init_host(struct platform_device *pdev,
153                 if (ap->flags & ATA_FLAG_EM)
154                         ap->em_message_type = hpriv->em_msg_type;
155  
156 +               rc = ahci_setup_port_privdata(ap);
157 +               if (rc)
158 +                       return rc;
159 +
160                 /* disabled/not-implemented port */
161                 if (!(hpriv->port_map & (1 << i)))
162                         ap->ops = &ata_dummy_port_ops;
163 diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
164 index f6cb1f1..c037f33 100644
165 --- a/drivers/ata/libata-core.c
166 +++ b/drivers/ata/libata-core.c
167 @@ -2024,6 +2024,9 @@ retry:
168                 }
169         }
170  
171 +       if (id[79] & SATA_DIPM)
172 +               dev->init_dipm = true;
173 +
174         *p_class = class;
175  
176         return 0;
177 @@ -5583,11 +5586,11 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
178  }
179  
180  /**
181 - *     sata_link_init_spd - Initialize link->sata_spd_limit
182 - *     @link: Link to configure sata_spd_limit for
183 + *     sata_link_init_config - Initialize link->sata_spd_limit and init_lpm
184 + *     @link: Link to configure sata_spd_limit and init_lpm for
185   *
186 - *     Initialize @link->[hw_]sata_spd_limit to the currently
187 - *     configured value.
188 + *     Initialize @link->[hw_]sata_spd_limit and @link->init_lpm to the
189 + *     currently configured value.
190   *
191   *     LOCKING:
192   *     Kernel thread context (may sleep).
193 @@ -5595,7 +5598,7 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
194   *     RETURNS:
195   *     0 on success, -errno on failure.
196   */
197 -int sata_link_init_spd(struct ata_link *link)
198 +int sata_link_init_config(struct ata_link *link)
199  {
200         u8 spd;
201         int rc;
202 @@ -5612,6 +5615,8 @@ int sata_link_init_spd(struct ata_link *link)
203  
204         link->sata_spd_limit = link->hw_sata_spd_limit;
205  
206 +       link->init_lpm = (link->saved_scontrol >> 8) & 0x7;
207 +
208         return 0;
209  }
210  
211 @@ -6161,9 +6166,9 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
212                         ap->cbl = ATA_CBL_SATA;
213  
214                 /* init sata_spd_limit to the current value */
215 -               sata_link_init_spd(&ap->link);
216 +               sata_link_init_config(&ap->link);
217                 if (ap->slave_link)
218 -                       sata_link_init_spd(ap->slave_link);
219 +                       sata_link_init_config(ap->slave_link);
220  
221                 /* print per-port info to dmesg */
222                 xfer_mask = ata_pack_xfermask(ap->pio_mask, ap->mwdma_mask,
223 diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c
224 index 7ccc084..b9f7ce8 100644
225 --- a/drivers/ata/libata-pmp.c
226 +++ b/drivers/ata/libata-pmp.c
227 @@ -531,7 +531,7 @@ int sata_pmp_attach(struct ata_device *dev)
228                 ap->ops->pmp_attach(ap);
229  
230         ata_for_each_link(tlink, ap, EDGE)
231 -               sata_link_init_spd(tlink);
232 +               sata_link_init_config(tlink);
233  
234         return 0;
235  
236 diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
237 index a998a17..35016d6 100644
238 --- a/drivers/ata/libata.h
239 +++ b/drivers/ata/libata.h
240 @@ -99,7 +99,7 @@ extern bool ata_phys_link_online(struct ata_link *link);
241  extern bool ata_phys_link_offline(struct ata_link *link);
242  extern void ata_dev_init(struct ata_device *dev);
243  extern void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp);
244 -extern int sata_link_init_spd(struct ata_link *link);
245 +extern int sata_link_init_config(struct ata_link *link);
246  extern int ata_task_ioctl(struct scsi_device *scsidev, void __user *arg);
247  extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
248  extern struct ata_port *ata_port_alloc(struct ata_host *host);
249 diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
250 index 24e311f..a2adf3f 100644
251 --- a/drivers/ata/sata_highbank.c
252 +++ b/drivers/ata/sata_highbank.c
253 @@ -556,6 +556,10 @@ static int ahci_highbank_probe(struct platform_device *pdev)
254                 if (ap->flags & ATA_FLAG_EM)
255                         ap->em_message_type = hpriv->em_msg_type;
256  
257 +               rc = ahci_setup_port_privdata(ap);
258 +               if (rc)
259 +                       goto err0;
260 +
261                 /* disabled/not-implemented port */
262                 if (!(hpriv->port_map & (1 << i)))
263                         ap->ops = &ata_dummy_port_ops;
264 diff --git a/include/linux/libata.h b/include/linux/libata.h
265 index 8dad4a3..31c149b 100644
266 --- a/include/linux/libata.h
267 +++ b/include/linux/libata.h
268 @@ -719,6 +719,8 @@ struct ata_device {
269         int                     spdn_cnt;
270         /* ering is CLEAR_END, read comment above CLEAR_END */
271         struct ata_ering        ering;
272 +       /* Initial DIPM configuration */
273 +       bool                    init_dipm;
274  };
275  
276  /* Fields between ATA_DEVICE_CLEAR_BEGIN and ATA_DEVICE_CLEAR_END are
277 @@ -800,6 +800,7 @@ struct ata_link {
278         struct ata_device       device[ATA_MAX_DEVICES];
279  
280         unsigned long           last_lpm_change; /* when last LPM change happened */
281 +       u8                      init_lpm; /* initial lpm configuration */
282  };
283  #define ATA_LINK_CLEAR_BEGIN           offsetof(struct ata_link, active_tag)
284  #define ATA_LINK_CLEAR_END             offsetof(struct ata_link, device[0])
285 -- 
286 2.3.5
287
288 --
289 To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
290 the body of a message to majordomo@vger.kernel.org
291 More majordomo info at  http://vger.kernel.org/majordomo-info.html
292 Please read the FAQ at  http://www.tux.org/lkml/
293 From:   Matthew Garrett <mjg59@coreos.com>
294 Date:   Sat, 18 Apr 2015 08:26:35 -0700
295 Subject: [PATCH 2/3] libata: Add firmware_default LPM policy
296
297 System vendors may configure SATA link power management appropriately for
298 their systems in firmware, based on their knowledge of the hardware
299 installed. Add an additional LPM policy designed to inherit the
300 configuration provided by the firmware.
301
302 Signed-off-by: Matthew Garrett <mjg59@coreos.com>
303 ---
304  .../scsi/link_power_management_policy.txt          |  5 +-
305  drivers/ata/libahci.c                              | 62 +++++++++++++++-------
306  drivers/ata/libata-core.c                          |  7 ++-
307  drivers/ata/libata-eh.c                            | 15 +++---
308  drivers/ata/libata-scsi.c                          |  1 +
309  include/linux/libata.h                             |  1 +
310  6 files changed, 63 insertions(+), 28 deletions(-)
311
312 diff --git a/Documentation/scsi/link_power_management_policy.txt b/Documentation/scsi/link_power_management_policy.txt
313 index d18993d..0285601 100644
314 --- a/Documentation/scsi/link_power_management_policy.txt
315 +++ b/Documentation/scsi/link_power_management_policy.txt
316 @@ -1,8 +1,11 @@
317  This parameter allows the user to set the link (interface) power management.
318 -There are 3 possible options:
319 +There are 4 possible options:
320  
321  Value                  Effect
322  ----------------------------------------------------------------------------
323 +firmware_defaults      Inherit configuration from the state programmed by
324 +                       the firmware during system init.
325 +
326  min_power              Tell the controller to try to make the link use the
327                         least possible power when possible.  This may
328                         sacrifice some performance due to increased latency
329 diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
330 index f0c7120..fabcff4 100644
331 --- a/drivers/ata/libahci.c
332 +++ b/drivers/ata/libahci.c
333 @@ -684,6 +684,7 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
334  {
335         struct ata_port *ap = link->ap;
336         struct ahci_host_priv *hpriv = ap->host->private_data;
337 +       struct ahci_port_priv *ppriv = ap->private_data;
338         struct ahci_port_priv *pp = ap->private_data;
339         void __iomem *port_mmio = ahci_port_base(ap);
340  
341 @@ -701,10 +702,10 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
342  
343         if (hpriv->cap & HOST_CAP_ALPM) {
344                 u32 cmd = readl(port_mmio + PORT_CMD);
345 +               if (!(hints & ATA_LPM_WAKE_ONLY))
346 +                       cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
347  
348                 if (policy == ATA_LPM_MAX_POWER || !(hints & ATA_LPM_HIPM)) {
349 -                       if (!(hints & ATA_LPM_WAKE_ONLY))
350 -                               cmd &= ~(PORT_CMD_ASP | PORT_CMD_ALPE);
351                         cmd |= PORT_CMD_ICC_ACTIVE;
352  
353                         writel(cmd, port_mmio + PORT_CMD);
354 @@ -711,6 +712,13 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
355  
356                         if (hints & ATA_LPM_WAKE_ONLY)
357                                 return 0;
358 +               } else if (policy == ATA_LPM_FIRMWARE_DEFAULTS) {
359 +                       if (ppriv->init_alpe)
360 +                               cmd |= PORT_CMD_ALPE;
361 +                       if (ppriv->init_asp)
362 +                               cmd |= PORT_CMD_ASP;
363 +
364 +                       writel(cmd, port_mmio + PORT_CMD);
365                 } else {
366                         cmd |= PORT_CMD_ALPE;
367                         if (policy == ATA_LPM_MIN_POWER)
368 @@ -725,10 +733,17 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
369         if ((hpriv->cap2 & HOST_CAP2_SDS) &&
370             (hpriv->cap2 & HOST_CAP2_SADM) &&
371             (link->device->flags & ATA_DFLAG_DEVSLP)) {
372 -               if (policy == ATA_LPM_MIN_POWER)
373 +               switch (policy) {
374 +               case ATA_LPM_MIN_POWER:
375                         ahci_set_aggressive_devslp(ap, true);
376 -               else
377 +                       break;
378 +               case ATA_LPM_FIRMWARE_DEFAULTS:
379 +                       ahci_set_aggressive_devslp(ap, ppriv->init_devslp);
380 +                       break;
381 +               default:
382                         ahci_set_aggressive_devslp(ap, false);
383 +                       break;
384 +               }
385         }
386  
387         if (policy == ATA_LPM_MAX_POWER) {
388 @@ -1995,6 +2010,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc)
389  static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
390  {
391         struct ahci_host_priv *hpriv = ap->host->private_data;
392 +       struct ahci_port_priv *ppriv = ap->private_data;
393         void __iomem *port_mmio = ahci_port_base(ap);
394         struct ata_device *dev = ap->link.device;
395         u32 devslp, dm, dito, mdat, deto;
396 @@ -2030,26 +2046,32 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
397         if (rc)
398                 return;
399  
400 -       dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
401 -       dito = devslp_idle_timeout / (dm + 1);
402 -       if (dito > 0x3ff)
403 -               dito = 0x3ff;
404 +       if (ppriv->init_devslp) {
405 +               dito = ppriv->init_dito;
406 +               deto = ppriv->init_deto;
407 +               mdat = ppriv->init_mdat;
408 +       } else {
409 +               dm = (devslp & PORT_DEVSLP_DM_MASK) >> PORT_DEVSLP_DM_OFFSET;
410 +               dito = devslp_idle_timeout / (dm + 1);
411 +               if (dito > 0x3ff)
412 +                       dito = 0x3ff;
413  
414 -       /* Use the nominal value 10 ms if the read MDAT is zero,
415 -        * the nominal value of DETO is 20 ms.
416 -        */
417 -       if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
418 -           ATA_LOG_DEVSLP_VALID_MASK) {
419 -               mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
420 -                      ATA_LOG_DEVSLP_MDAT_MASK;
421 -               if (!mdat)
422 +               /* Use the nominal value 10 ms if the read MDAT is zero,
423 +                * the nominal value of DETO is 20 ms.
424 +                */
425 +               if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
426 +                   ATA_LOG_DEVSLP_VALID_MASK) {
427 +                       mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
428 +                               ATA_LOG_DEVSLP_MDAT_MASK;
429 +                       if (!mdat)
430 +                               mdat = 10;
431 +                       deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
432 +                       if (!deto)
433 +                               deto = 20;
434 +               } else {
435                         mdat = 10;
436 -               deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
437 -               if (!deto)
438                         deto = 20;
439 -       } else {
440 -               mdat = 10;
441 -               deto = 20;
442 +               }
443         }
444  
445         devslp |= ((dito << PORT_DEVSLP_DITO_OFFSET) |
446 diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
447 index c037f33..0a78f01 100644
448 --- a/drivers/ata/libata-core.c
449 +++ b/drivers/ata/libata-core.c
450 @@ -2024,7 +2024,7 @@ retry:
451                 }
452         }
453  
454 -       if (id[79] & SATA_DIPM)
455 +       if (id[79] & (1 << SATA_DIPM))
456                 dev->init_dipm = true;
457  
458         *p_class = class;
459 @@ -3672,6 +3672,11 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
460                 return rc;
461  
462         switch (policy) {
463 +       case ATA_LPM_FIRMWARE_DEFAULTS:
464 +               /* use the values we read at probe */
465 +               scontrol &= ~(0x7 << 8);
466 +               scontrol |= (link->init_lpm << 8);
467 +               break;
468         case ATA_LPM_MAX_POWER:
469                 /* disable all LPM transitions */
470                 scontrol |= (0x7 << 8);
471 diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
472 index 07f41be..c36fa56 100644
473 --- a/drivers/ata/libata-eh.c
474 +++ b/drivers/ata/libata-eh.c
475 @@ -3519,9 +3519,9 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
476                 return 0;
477  
478         /*
479 -        * DIPM is enabled only for MIN_POWER as some devices
480 -        * misbehave when the host NACKs transition to SLUMBER.  Order
481 -        * device and link configurations such that the host always
482 +        * DIPM is enabled only for MIN_POWER and FIRMWARE_DEFAULT as some
483 +        * devices misbehave when the host NACKs transition to SLUMBER.
484 +        * Order device and link configurations such that the host always
485          * allows DIPM requests.
486          */
487         ata_for_each_dev(dev, link, ENABLED) {
488 @@ -3581,10 +3581,13 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
489         if (ap && ap->slave_link)
490                 ap->slave_link->lpm_policy = policy;
491  
492 -       /* host config updated, enable DIPM if transitioning to MIN_POWER */
493 +       /* host config updated, enable DIPM if transitioning to MIN_POWER or
494 +        * FIRMWARE_DEFAULT when enabled by firmware
495 +        */
496         ata_for_each_dev(dev, link, ENABLED) {
497 -               if (policy == ATA_LPM_MIN_POWER && !no_dipm &&
498 -                   ata_id_has_dipm(dev->id)) {
499 +               if ((policy == ATA_LPM_MIN_POWER && !no_dipm &&
500 +                    ata_id_has_dipm(dev->id)) ||
501 +                   (policy == ATA_LPM_FIRMWARE_DEFAULTS && dev->init_dipm)) {
502                         err_mask = ata_dev_set_feature(dev,
503                                         SETFEATURES_SATA_ENABLE, SATA_DIPM);
504                         if (err_mask && err_mask != AC_ERR_DEV) {
505 diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
506 index 3131adc..f1ea052 100644
507 --- a/drivers/ata/libata-scsi.c
508 +++ b/drivers/ata/libata-scsi.c
509 @@ -107,6 +107,7 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
510  static const char *ata_lpm_policy_names[] = {
511         [ATA_LPM_UNKNOWN]       = "max_performance",
512         [ATA_LPM_MAX_POWER]     = "max_performance",
513 +       [ATA_LPM_FIRMWARE_DEFAULTS] = "firmware_defaults",
514         [ATA_LPM_MED_POWER]     = "medium_power",
515         [ATA_LPM_MIN_POWER]     = "min_power",
516  };
517 diff --git a/include/linux/libata.h b/include/linux/libata.h
518 index 31c149b..57b465d 100644
519 --- a/include/linux/libata.h
520 +++ b/include/linux/libata.h
521 @@ -507,6 +507,7 @@ enum ata_completion_errors {
522  enum ata_lpm_policy {
523         ATA_LPM_UNKNOWN,
524         ATA_LPM_MAX_POWER,
525 +       ATA_LPM_FIRMWARE_DEFAULTS,
526         ATA_LPM_MED_POWER,
527         ATA_LPM_MIN_POWER,
528  };
529 -- 
530 2.3.5
531
532 --
533 To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
534 the body of a message to majordomo@vger.kernel.org
535 More majordomo info at  http://vger.kernel.org/majordomo-info.html
536 Please read the FAQ at  http://www.tux.org/lkml/
537 From:   Matthew Garrett <mjg59@coreos.com>
538 Date:   Sat, 18 Apr 2015 08:26:36 -0700
539 Subject: [PATCH 3/3] libata: Change medium_power LPM policy to match Intel recommendations
540
541 Intel publish a document on designing energy efficient SATA devices at
542 http://www.intel.com/content/dam/doc/reference-guide/sata-devices-implementation-recommendations.pdf
543 which recommends that ALPE be set, ASPE be cleared and that DIPM be enabled
544 on the device. Right now we have no policy that matches that - medium_power
545 does not enable DIPM and min_power sets ASPE. Change medium_power to
546 implement these recommendations, with the addition of devslp state being
547 inherited from the initial configuration. With luck this will provide
548 reasonable power savings without causing the device breakages we
549 occasionally see with the min_power policy.
550
551 Signed-off-by: Matthew Garrett <mjg59@coreos.com>
552 ---
553  drivers/ata/libahci.c     |  1 +
554  drivers/ata/libata-core.c |  4 ----
555  drivers/ata/libata-eh.c   | 10 ++++------
556  3 files changed, 5 insertions(+), 10 deletions(-)
557
558 diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
559 index fabcff4..8efacb9 100644
560 --- a/drivers/ata/libahci.c
561 +++ b/drivers/ata/libahci.c
562 @@ -738,6 +738,7 @@ static int ahci_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
563                         ahci_set_aggressive_devslp(ap, true);
564                         break;
565                 case ATA_LPM_FIRMWARE_DEFAULTS:
566 +               case ATA_LPM_MED_POWER:
567                         ahci_set_aggressive_devslp(ap, ppriv->init_devslp);
568                         break;
569                 default:
570 diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
571 index 0a78f01..99a7b8f 100644
572 --- a/drivers/ata/libata-core.c
573 +++ b/drivers/ata/libata-core.c
574 @@ -3687,10 +3687,6 @@ int sata_link_scr_lpm(struct ata_link *link, enum ata_lpm_policy policy,
575                 }
576                 break;
577         case ATA_LPM_MED_POWER:
578 -               /* allow LPM to PARTIAL */
579 -               scontrol &= ~(0x1 << 8);
580 -               scontrol |= (0x6 << 8);
581 -               break;
582         case ATA_LPM_MIN_POWER:
583                 if (ata_link_nr_enabled(link) > 0)
584                         /* no restrictions on LPM transitions */
585 diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
586 index c36fa56..25d5f37 100644
587 --- a/drivers/ata/libata-eh.c
588 +++ b/drivers/ata/libata-eh.c
589 @@ -3519,8 +3519,6 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
590                 return 0;
591  
592         /*
593 -        * DIPM is enabled only for MIN_POWER and FIRMWARE_DEFAULT as some
594 -        * devices misbehave when the host NACKs transition to SLUMBER.
595          * Order device and link configurations such that the host always
596          * allows DIPM requests.
597          */
598 @@ -3540,7 +3538,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
599                         hints &= ~ATA_LPM_HIPM;
600  
601                 /* disable DIPM before changing link config */
602 -               if (policy != ATA_LPM_MIN_POWER && dipm) {
603 +               if (policy < ATA_LPM_MED_POWER && dipm) {
604                         err_mask = ata_dev_set_feature(dev,
605                                         SETFEATURES_SATA_DISABLE, SATA_DIPM);
606                         if (err_mask && err_mask != AC_ERR_DEV) {
607 @@ -3581,11 +3579,11 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
608         if (ap && ap->slave_link)
609                 ap->slave_link->lpm_policy = policy;
610  
611 -       /* host config updated, enable DIPM if transitioning to MIN_POWER or
612 -        * FIRMWARE_DEFAULT when enabled by firmware
613 +       /* host config updated, enable DIPM if transitioning to MED_POWER,
614 +        * MIN_POWER or FIRMWARE_DEFAULT when enabled by firmware
615          */
616         ata_for_each_dev(dev, link, ENABLED) {
617 -               if ((policy == ATA_LPM_MIN_POWER && !no_dipm &&
618 +               if ((policy >= ATA_LPM_MED_POWER && !no_dipm &&
619                      ata_id_has_dipm(dev->id)) ||
620                     (policy == ATA_LPM_FIRMWARE_DEFAULTS && dev->init_dipm)) {
621                         err_mask = ata_dev_set_feature(dev,
622 -- 
623 2.3.5
624
625 --
626 To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
627 the body of a message to majordomo@vger.kernel.org
628 More majordomo info at  http://vger.kernel.org/majordomo-info.html
629 Please read the FAQ at  http://www.tux.org/lkml/
This page took 0.083723 seconds and 3 git commands to generate.