kernel-4.8.4 work 1
This commit is contained in:
Binary file not shown.
+35
@@ -0,0 +1,35 @@
|
||||
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
|
||||
index 425544b..0c2e252 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_pm.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_pm.c
|
||||
@@ -3362,13 +3362,15 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
|
||||
int num_active;
|
||||
int id, i;
|
||||
|
||||
+ /* Clear the partitioning for disabled planes. */
|
||||
+ memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
|
||||
+ memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe]));
|
||||
+
|
||||
if (WARN_ON(!state))
|
||||
return 0;
|
||||
|
||||
if (!cstate->base.active) {
|
||||
ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0;
|
||||
- memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe]));
|
||||
- memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -4054,6 +4056,12 @@ skl_compute_ddb(struct drm_atomic_state *state)
|
||||
intel_state->wm_results.dirty_pipes = ~0;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * We're not recomputing for the pipes not included in the commit, so
|
||||
+ * make sure we start with the current state.
|
||||
+ */
|
||||
+ memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb));
|
||||
+
|
||||
for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) {
|
||||
struct intel_crtc_state *cstate;
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
From b5a9b340789b2b24c6896bcf7a065c31a4db671c Mon Sep 17 00:00:00 2001
|
||||
From: Vincent Guittot <vincent.guittot@linaro.org>
|
||||
Date: Wed, 19 Oct 2016 14:45:23 +0200
|
||||
Subject: [PATCH] sched/fair: Fix incorrect task group ->load_avg
|
||||
|
||||
A scheduler performance regression has been reported by Joseph Salisbury,
|
||||
which he bisected back to:
|
||||
|
||||
3d30544f0212 ("sched/fair: Apply more PELT fixes)
|
||||
|
||||
The regression triggers when several levels of task groups are involved
|
||||
(read: SystemD) and cpu_possible_mask != cpu_present_mask.
|
||||
|
||||
The root cause is that group entity's load (tg_child->se[i]->avg.load_avg)
|
||||
is initialized to scale_load_down(se->load.weight). During the creation of
|
||||
a child task group, its group entities on possible CPUs are attached to
|
||||
parent's cfs_rq (tg_parent) and their loads are added to the parent's load
|
||||
(tg_parent->load_avg) with update_tg_load_avg().
|
||||
|
||||
But only the load on online CPUs will then be updated to reflect real load,
|
||||
whereas load on other CPUs will stay at the initial value.
|
||||
|
||||
The result is a tg_parent->load_avg that is higher than the real load, the
|
||||
weight of group entities (tg_parent->se[i]->load.weight) on online CPUs is
|
||||
smaller than it should be, and the task group gets a less running time than
|
||||
what it could expect.
|
||||
|
||||
( This situation can be detected with /proc/sched_debug. The ".tg_load_avg"
|
||||
of the task group will be much higher than sum of ".tg_load_avg_contrib"
|
||||
of online cfs_rqs of the task group. )
|
||||
|
||||
The load of group entities don't have to be intialized to something else
|
||||
than 0 because their load will increase when an entity is attached.
|
||||
|
||||
Reported-by: Joseph Salisbury <joseph.salisbury@canonical.com>
|
||||
Tested-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
|
||||
Signed-off-by: Vincent Guittot <vincent.guittot@linaro.org>
|
||||
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
|
||||
Cc: <stable@vger.kernel.org> # 4.8.x
|
||||
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Cc: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: joonwoop@codeaurora.org
|
||||
Fixes: 3d30544f0212 ("sched/fair: Apply more PELT fixes)
|
||||
Link: http://lkml.kernel.org/r/1476881123-10159-1-git-send-email-vincent.guittot@linaro.org
|
||||
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
||||
---
|
||||
kernel/sched/fair.c | 9 ++++++++-
|
||||
1 file changed, 8 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
|
||||
index 76ee7de..d941c97 100644
|
||||
--- a/kernel/sched/fair.c
|
||||
+++ b/kernel/sched/fair.c
|
||||
@@ -690,7 +690,14 @@ void init_entity_runnable_average(struct sched_entity *se)
|
||||
* will definitely be update (after enqueue).
|
||||
*/
|
||||
sa->period_contrib = 1023;
|
||||
- sa->load_avg = scale_load_down(se->load.weight);
|
||||
+ /*
|
||||
+ * Tasks are intialized with full load to be seen as heavy tasks until
|
||||
+ * they get a chance to stabilize to their real load level.
|
||||
+ * Group entities are intialized with zero load to reflect the fact that
|
||||
+ * nothing has been attached to the task group yet.
|
||||
+ */
|
||||
+ if (entity_is_task(se))
|
||||
+ sa->load_avg = scale_load_down(se->load.weight);
|
||||
sa->load_sum = sa->load_avg * LOAD_AVG_MAX;
|
||||
/*
|
||||
* At this point, util_avg won't be used in select_task_rq_fair anyway
|
||||
--
|
||||
2.10.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,213 @@
|
||||
|
||||
From: Sabrina Dubroca <sd@queasysnail.net>
|
||||
|
||||
https://bugzilla.redhat.com/show_bug.cgi?id=1375944
|
||||
https://patchwork.ozlabs.org/patch/680412/
|
||||
|
||||
|
||||
Currently, GRO can do unlimited recursion through the gro_receive
|
||||
handlers. This was fixed for tunneling protocols by limiting tunnel GRO
|
||||
to one level with encap_mark, but both VLAN and TEB still have this
|
||||
problem. Thus, the kernel is vulnerable to a stack overflow, if we
|
||||
receive a packet composed entirely of VLAN headers.
|
||||
|
||||
This patch adds a recursion counter to the GRO layer to prevent stack
|
||||
overflow. When a gro_receive function hits the recursion limit, GRO is
|
||||
aborted for this skb and it is processed normally.
|
||||
|
||||
Thanks to Vladimír Beneš <vbenes@redhat.com> for the initial bug report.
|
||||
|
||||
Fixes: CVE-2016-7039
|
||||
Fixes: 9b174d88c257 ("net: Add Transparent Ethernet Bridging GRO support.")
|
||||
Fixes: 66e5133f19e9 ("vlan: Add GRO support for non hardware accelerated vlan")
|
||||
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
|
||||
Reviewed-by: Jiri Benc <jbenc@redhat.com>
|
||||
Acked-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
|
||||
|
||||
|
||||
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
|
||||
index 3c20e87bb761..16af1ce99233 100644
|
||||
--- a/drivers/net/geneve.c
|
||||
+++ b/drivers/net/geneve.c
|
||||
@@ -453,7 +453,7 @@ static struct sk_buff **geneve_gro_receive(struct sock *sk,
|
||||
|
||||
skb_gro_pull(skb, gh_len);
|
||||
skb_gro_postpull_rcsum(skb, gh, gh_len);
|
||||
- pp = ptype->callbacks.gro_receive(head, skb);
|
||||
+ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
|
||||
flush = 0;
|
||||
|
||||
out_unlock:
|
||||
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
|
||||
index e7d16687538b..c1639a3e95a4 100644
|
||||
--- a/drivers/net/vxlan.c
|
||||
+++ b/drivers/net/vxlan.c
|
||||
@@ -583,7 +583,7 @@ static struct sk_buff **vxlan_gro_receive(struct sock *sk,
|
||||
}
|
||||
}
|
||||
|
||||
- pp = eth_gro_receive(head, skb);
|
||||
+ pp = call_gro_receive(eth_gro_receive, head, skb);
|
||||
flush = 0;
|
||||
|
||||
out:
|
||||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
|
||||
index 136ae6bbe81e..11a7218c3661 100644
|
||||
--- a/include/linux/netdevice.h
|
||||
+++ b/include/linux/netdevice.h
|
||||
@@ -2169,7 +2169,10 @@ struct napi_gro_cb {
|
||||
/* Used to determine if flush_id can be ignored */
|
||||
u8 is_atomic:1;
|
||||
|
||||
- /* 5 bit hole */
|
||||
+ /* Number of gro_receive callbacks this packet already went through */
|
||||
+ u8 recursion_counter:4;
|
||||
+
|
||||
+ /* 1 bit hole */
|
||||
|
||||
/* used to support CHECKSUM_COMPLETE for tunneling protocols */
|
||||
__wsum csum;
|
||||
@@ -2180,6 +2183,25 @@ struct napi_gro_cb {
|
||||
|
||||
#define NAPI_GRO_CB(skb) ((struct napi_gro_cb *)(skb)->cb)
|
||||
|
||||
+#define GRO_RECURSION_LIMIT 15
|
||||
+static inline int gro_recursion_inc_test(struct sk_buff *skb)
|
||||
+{
|
||||
+ return ++NAPI_GRO_CB(skb)->recursion_counter == GRO_RECURSION_LIMIT;
|
||||
+}
|
||||
+
|
||||
+typedef struct sk_buff **(*gro_receive_t)(struct sk_buff **, struct sk_buff *);
|
||||
+static inline struct sk_buff **call_gro_receive(gro_receive_t cb,
|
||||
+ struct sk_buff **head,
|
||||
+ struct sk_buff *skb)
|
||||
+{
|
||||
+ if (gro_recursion_inc_test(skb)) {
|
||||
+ NAPI_GRO_CB(skb)->flush |= 1;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ return cb(head, skb);
|
||||
+}
|
||||
+
|
||||
struct packet_type {
|
||||
__be16 type; /* This is really htons(ether_type). */
|
||||
struct net_device *dev; /* NULL is wildcarded here */
|
||||
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
|
||||
index 8de138d3306b..f2531ad66b68 100644
|
||||
--- a/net/8021q/vlan.c
|
||||
+++ b/net/8021q/vlan.c
|
||||
@@ -664,7 +664,7 @@ static struct sk_buff **vlan_gro_receive(struct sk_buff **head,
|
||||
|
||||
skb_gro_pull(skb, sizeof(*vhdr));
|
||||
skb_gro_postpull_rcsum(skb, vhdr, sizeof(*vhdr));
|
||||
- pp = ptype->callbacks.gro_receive(head, skb);
|
||||
+ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
diff --git a/net/core/dev.c b/net/core/dev.c
|
||||
index f1fe26f66458..f7cd4b8b035d 100644
|
||||
--- a/net/core/dev.c
|
||||
+++ b/net/core/dev.c
|
||||
@@ -4511,6 +4511,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff
|
||||
NAPI_GRO_CB(skb)->flush = 0;
|
||||
NAPI_GRO_CB(skb)->free = 0;
|
||||
NAPI_GRO_CB(skb)->encap_mark = 0;
|
||||
+ NAPI_GRO_CB(skb)->recursion_counter = 0;
|
||||
NAPI_GRO_CB(skb)->is_fou = 0;
|
||||
NAPI_GRO_CB(skb)->is_atomic = 1;
|
||||
NAPI_GRO_CB(skb)->gro_remcsum_start = 0;
|
||||
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
|
||||
index 66dff5e3d772..02acfff36028 100644
|
||||
--- a/net/ethernet/eth.c
|
||||
+++ b/net/ethernet/eth.c
|
||||
@@ -439,7 +439,7 @@ struct sk_buff **eth_gro_receive(struct sk_buff **head,
|
||||
|
||||
skb_gro_pull(skb, sizeof(*eh));
|
||||
skb_gro_postpull_rcsum(skb, eh, sizeof(*eh));
|
||||
- pp = ptype->callbacks.gro_receive(head, skb);
|
||||
+ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
|
||||
index 1effc986739e..9648c97e541f 100644
|
||||
--- a/net/ipv4/af_inet.c
|
||||
+++ b/net/ipv4/af_inet.c
|
||||
@@ -1391,7 +1391,7 @@ struct sk_buff **inet_gro_receive(struct sk_buff **head, struct sk_buff *skb)
|
||||
skb_gro_pull(skb, sizeof(*iph));
|
||||
skb_set_transport_header(skb, skb_gro_offset(skb));
|
||||
|
||||
- pp = ops->callbacks.gro_receive(head, skb);
|
||||
+ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
diff --git a/net/ipv4/fou.c b/net/ipv4/fou.c
|
||||
index cf50f7e2b012..030d1531e897 100644
|
||||
--- a/net/ipv4/fou.c
|
||||
+++ b/net/ipv4/fou.c
|
||||
@@ -249,7 +249,7 @@ static struct sk_buff **fou_gro_receive(struct sock *sk,
|
||||
if (!ops || !ops->callbacks.gro_receive)
|
||||
goto out_unlock;
|
||||
|
||||
- pp = ops->callbacks.gro_receive(head, skb);
|
||||
+ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
@@ -441,7 +441,7 @@ static struct sk_buff **gue_gro_receive(struct sock *sk,
|
||||
if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive))
|
||||
goto out_unlock;
|
||||
|
||||
- pp = ops->callbacks.gro_receive(head, skb);
|
||||
+ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
|
||||
flush = 0;
|
||||
|
||||
out_unlock:
|
||||
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
|
||||
index 96e0efecefa6..d5cac99170b1 100644
|
||||
--- a/net/ipv4/gre_offload.c
|
||||
+++ b/net/ipv4/gre_offload.c
|
||||
@@ -229,7 +229,7 @@ static struct sk_buff **gre_gro_receive(struct sk_buff **head,
|
||||
/* Adjusted NAPI_GRO_CB(skb)->csum after skb_gro_pull()*/
|
||||
skb_gro_postpull_rcsum(skb, greh, grehlen);
|
||||
|
||||
- pp = ptype->callbacks.gro_receive(head, skb);
|
||||
+ pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
|
||||
flush = 0;
|
||||
|
||||
out_unlock:
|
||||
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
|
||||
index f9333c963607..7b5879bcd08b 100644
|
||||
--- a/net/ipv4/udp_offload.c
|
||||
+++ b/net/ipv4/udp_offload.c
|
||||
@@ -295,7 +295,13 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,
|
||||
|
||||
skb_gro_pull(skb, sizeof(struct udphdr)); /* pull encapsulating udp header */
|
||||
skb_gro_postpull_rcsum(skb, uh, sizeof(struct udphdr));
|
||||
- pp = udp_sk(sk)->gro_receive(sk, head, skb);
|
||||
+
|
||||
+ if (gro_recursion_inc_test(skb)) {
|
||||
+ flush = 1;
|
||||
+ pp = NULL;
|
||||
+ } else {
|
||||
+ pp = udp_sk(sk)->gro_receive(sk, head, skb);
|
||||
+ }
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
|
||||
index e7bfd55899a3..1fcf61f1cbc3 100644
|
||||
--- a/net/ipv6/ip6_offload.c
|
||||
+++ b/net/ipv6/ip6_offload.c
|
||||
@@ -246,7 +246,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head,
|
||||
|
||||
skb_gro_postpull_rcsum(skb, iph, nlen);
|
||||
|
||||
- pp = ops->callbacks.gro_receive(head, skb);
|
||||
+ pp = call_gro_receive(ops->callbacks.gro_receive, head, skb);
|
||||
|
||||
out_unlock:
|
||||
rcu_read_unlock();
|
||||
+426
@@ -0,0 +1,426 @@
|
||||
|
||||
From: Larry Finger <Larry.Finger@lwfinger.net>
|
||||
|
||||
In commit d86e64768859 ("rtlwifi: rtl818x: constify local structures"),
|
||||
the configuration struct for most of the drivers was changed to be
|
||||
constant. The problem is that five of the modified drivers need to be
|
||||
able to update the firmware name based on the exact model of the card.
|
||||
As the file names were stored in one of the members of that struct,
|
||||
these drivers would fail with a kernel BUG splat when they tried to
|
||||
update the firmware name.
|
||||
|
||||
Rather than reverting the previous commit, I used a suggestion by
|
||||
Johannes Berg and made the firmware file name pointers be local to
|
||||
the routines that update the software variables.
|
||||
|
||||
The configuration struct of rtl8192cu, which was not touched in the
|
||||
previous patch, is now constantfied.
|
||||
|
||||
Fixes: d86e64768859 ("rtlwifi: rtl818x: constify local structures")
|
||||
Suggested-by: Johannes Berg <johannes@sipsolutions.net>
|
||||
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
|
||||
Cc: Stable <stable@vger.kernel.org>
|
||||
Cc: Julia Lawall <Julia.Lawall@lip6.fr>
|
||||
---
|
||||
|
||||
V2 - Fix warnings that were generated for some compiler versions.
|
||||
---
|
||||
drivers/net/wireless/realtek/rtlwifi/core.c | 2 +-
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c | 8 ++++----
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c | 13 +++++--------
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c | 12 ++++++------
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c | 6 +++---
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c | 8 ++++----
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c | 9 +++++----
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c | 12 +++++-------
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c | 6 +++---
|
||||
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c | 18 +++++++++---------
|
||||
drivers/net/wireless/realtek/rtlwifi/wifi.h | 2 --
|
||||
11 files changed, 45 insertions(+), 51 deletions(-)
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/core.c b/drivers/net/wireless/realtek/rtlwifi/core.c
|
||||
index f95760c..8e7f23c 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/core.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/core.c
|
||||
@@ -111,7 +111,7 @@ static void rtl_fw_do_work(const struct firmware *firmware, void *context,
|
||||
if (!err)
|
||||
goto found_alt;
|
||||
}
|
||||
- pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
|
||||
+ pr_err("Selected firmware is not available\n");
|
||||
rtlpriv->max_fw_size = 0;
|
||||
return;
|
||||
}
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
|
||||
index e7b11b4..f361808 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
|
||||
@@ -86,6 +86,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
u8 tid;
|
||||
+ char *fw_name;
|
||||
|
||||
rtl8188ee_bt_reg_init(hw);
|
||||
rtlpriv->dm.dm_initialgain_enable = 1;
|
||||
@@ -169,10 +170,10 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
|
||||
return 1;
|
||||
}
|
||||
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8188efw.bin";
|
||||
+ fw_name = "rtlwifi/rtl8188efw.bin";
|
||||
rtlpriv->max_fw_size = 0x8000;
|
||||
- pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
- err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
+ pr_info("Using firmware %s\n", fw_name);
|
||||
+ err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_fw_cb);
|
||||
if (err) {
|
||||
@@ -284,7 +285,6 @@ static const struct rtl_hal_cfg rtl88ee_hal_cfg = {
|
||||
.bar_id = 2,
|
||||
.write_readback = true,
|
||||
.name = "rtl88e_pci",
|
||||
- .fw_name = "rtlwifi/rtl8188efw.bin",
|
||||
.ops = &rtl8188ee_hal_ops,
|
||||
.mod_params = &rtl88ee_mod_params,
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
|
||||
index 5c46a98..691ddef 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
|
||||
@@ -92,6 +92,7 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
+ char *fw_name = "rtlwifi/rtl8192cfwU.bin";
|
||||
|
||||
rtl8192ce_bt_reg_init(hw);
|
||||
|
||||
@@ -163,15 +164,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
/* request fw */
|
||||
- if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
|
||||
- !IS_92C_SERIAL(rtlhal->version))
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin";
|
||||
- else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version))
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin";
|
||||
+ if (IS_81XXC_VENDOR_UMC_B_CUT(rtlhal->version))
|
||||
+ fw_name = "rtlwifi/rtl8192cfwU_B.bin";
|
||||
|
||||
rtlpriv->max_fw_size = 0x4000;
|
||||
- pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
- err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
+ pr_info("Using firmware %s\n", fw_name);
|
||||
+ err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_fw_cb);
|
||||
if (err) {
|
||||
@@ -258,7 +256,6 @@ static const struct rtl_hal_cfg rtl92ce_hal_cfg = {
|
||||
.bar_id = 2,
|
||||
.write_readback = true,
|
||||
.name = "rtl92c_pci",
|
||||
- .fw_name = "rtlwifi/rtl8192cfw.bin",
|
||||
.ops = &rtl8192ce_hal_ops,
|
||||
.mod_params = &rtl92ce_mod_params,
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
|
||||
index 92588e0..b84e13a 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/sw.c
|
||||
@@ -55,6 +55,7 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
|
||||
{
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
int err;
|
||||
+ char *fw_name;
|
||||
|
||||
rtlpriv->dm.dm_initialgain_enable = true;
|
||||
rtlpriv->dm.dm_flag = 0;
|
||||
@@ -73,18 +74,18 @@ static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
|
||||
}
|
||||
if (IS_VENDOR_UMC_A_CUT(rtlpriv->rtlhal.version) &&
|
||||
!IS_92C_SERIAL(rtlpriv->rtlhal.version)) {
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_A.bin";
|
||||
+ fw_name = "rtlwifi/rtl8192cufw_A.bin";
|
||||
} else if (IS_81XXC_VENDOR_UMC_B_CUT(rtlpriv->rtlhal.version)) {
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_B.bin";
|
||||
+ fw_name = "rtlwifi/rtl8192cufw_B.bin";
|
||||
} else {
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cufw_TMSC.bin";
|
||||
+ fw_name = "rtlwifi/rtl8192cufw_TMSC.bin";
|
||||
}
|
||||
/* provide name of alternative file */
|
||||
rtlpriv->cfg->alt_fw_name = "rtlwifi/rtl8192cufw.bin";
|
||||
- pr_info("Loading firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
+ pr_info("Loading firmware %s\n", fw_name);
|
||||
rtlpriv->max_fw_size = 0x4000;
|
||||
err = request_firmware_nowait(THIS_MODULE, 1,
|
||||
- rtlpriv->cfg->fw_name, rtlpriv->io.dev,
|
||||
+ fw_name, rtlpriv->io.dev,
|
||||
GFP_KERNEL, hw, rtl_fw_cb);
|
||||
return err;
|
||||
}
|
||||
@@ -183,7 +184,6 @@ static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = {
|
||||
|
||||
static struct rtl_hal_cfg rtl92cu_hal_cfg = {
|
||||
.name = "rtl92c_usb",
|
||||
- .fw_name = "rtlwifi/rtl8192cufw.bin",
|
||||
.ops = &rtl8192cu_hal_ops,
|
||||
.mod_params = &rtl92cu_mod_params,
|
||||
.usb_interface_cfg = &rtl92cu_interface_cfg,
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
|
||||
index a9c39eb..2d65e40 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
|
||||
@@ -88,6 +88,7 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
|
||||
u8 tid;
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
+ char *fw_name = "rtlwifi/rtl8192defw.bin";
|
||||
|
||||
rtlpriv->dm.dm_initialgain_enable = true;
|
||||
rtlpriv->dm.dm_flag = 0;
|
||||
@@ -177,10 +178,10 @@ static int rtl92d_init_sw_vars(struct ieee80211_hw *hw)
|
||||
|
||||
rtlpriv->max_fw_size = 0x8000;
|
||||
pr_info("Driver for Realtek RTL8192DE WLAN interface\n");
|
||||
- pr_info("Loading firmware file %s\n", rtlpriv->cfg->fw_name);
|
||||
+ pr_info("Loading firmware file %s\n", fw_name);
|
||||
|
||||
/* request fw */
|
||||
- err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
+ err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_fw_cb);
|
||||
if (err) {
|
||||
@@ -262,7 +263,6 @@ static const struct rtl_hal_cfg rtl92de_hal_cfg = {
|
||||
.bar_id = 2,
|
||||
.write_readback = true,
|
||||
.name = "rtl8192de",
|
||||
- .fw_name = "rtlwifi/rtl8192defw.bin",
|
||||
.ops = &rtl8192de_hal_ops,
|
||||
.mod_params = &rtl92de_mod_params,
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
|
||||
index ac299cb..46b605de3 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
|
||||
@@ -91,6 +91,7 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw)
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
int err = 0;
|
||||
+ char *fw_name;
|
||||
|
||||
rtl92ee_bt_reg_init(hw);
|
||||
rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
|
||||
@@ -170,11 +171,11 @@ int rtl92ee_init_sw_vars(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
/* request fw */
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8192eefw.bin";
|
||||
+ fw_name = "rtlwifi/rtl8192eefw.bin";
|
||||
|
||||
rtlpriv->max_fw_size = 0x8000;
|
||||
- pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
- err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
+ pr_info("Using firmware %s\n", fw_name);
|
||||
+ err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_fw_cb);
|
||||
if (err) {
|
||||
@@ -266,7 +267,6 @@ static const struct rtl_hal_cfg rtl92ee_hal_cfg = {
|
||||
.bar_id = 2,
|
||||
.write_readback = true,
|
||||
.name = "rtl92ee_pci",
|
||||
- .fw_name = "rtlwifi/rtl8192eefw.bin",
|
||||
.ops = &rtl8192ee_hal_ops,
|
||||
.mod_params = &rtl92ee_mod_params,
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
|
||||
index a652d45..998cefb 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
|
||||
@@ -85,12 +85,13 @@ static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
|
||||
struct ieee80211_hw *hw = context;
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rt_firmware *pfirmware = NULL;
|
||||
+ char *fw_name = "rtlwifi/rtl8192sefw.bin";
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
|
||||
"Firmware callback routine entered!\n");
|
||||
complete(&rtlpriv->firmware_loading_complete);
|
||||
if (!firmware) {
|
||||
- pr_err("Firmware %s not available\n", rtlpriv->cfg->fw_name);
|
||||
+ pr_err("Firmware %s not available\n", fw_name);
|
||||
rtlpriv->max_fw_size = 0;
|
||||
return;
|
||||
}
|
||||
@@ -113,6 +114,7 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
int err = 0;
|
||||
u16 earlyrxthreshold = 7;
|
||||
+ char *fw_name = "rtlwifi/rtl8192sefw.bin";
|
||||
|
||||
rtlpriv->dm.dm_initialgain_enable = true;
|
||||
rtlpriv->dm.dm_flag = 0;
|
||||
@@ -210,9 +212,9 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
|
||||
rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 +
|
||||
sizeof(struct fw_hdr);
|
||||
pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
|
||||
- "Loading firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
+ "Loading firmware %s\n", fw_name);
|
||||
/* request fw */
|
||||
- err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
+ err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl92se_fw_cb);
|
||||
if (err) {
|
||||
@@ -306,7 +308,6 @@ static const struct rtl_hal_cfg rtl92se_hal_cfg = {
|
||||
.bar_id = 1,
|
||||
.write_readback = false,
|
||||
.name = "rtl92s_pci",
|
||||
- .fw_name = "rtlwifi/rtl8192sefw.bin",
|
||||
.ops = &rtl8192se_hal_ops,
|
||||
.mod_params = &rtl92se_mod_params,
|
||||
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
|
||||
index 89c828a..c51a9e8 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
|
||||
@@ -94,6 +94,7 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw)
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
int err = 0;
|
||||
+ char *fw_name = "rtlwifi/rtl8723fw.bin";
|
||||
|
||||
rtl8723e_bt_reg_init(hw);
|
||||
|
||||
@@ -176,14 +177,12 @@ int rtl8723e_init_sw_vars(struct ieee80211_hw *hw)
|
||||
return 1;
|
||||
}
|
||||
|
||||
- if (IS_VENDOR_8723_A_CUT(rtlhal->version))
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw.bin";
|
||||
- else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8723fw_B.bin";
|
||||
+ if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
|
||||
+ fw_name = "rtlwifi/rtl8723fw_B.bin";
|
||||
|
||||
rtlpriv->max_fw_size = 0x6000;
|
||||
- pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
- err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
+ pr_info("Using firmware %s\n", fw_name);
|
||||
+ err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_fw_cb);
|
||||
if (err) {
|
||||
@@ -280,7 +279,6 @@ static const struct rtl_hal_cfg rtl8723e_hal_cfg = {
|
||||
.bar_id = 2,
|
||||
.write_readback = true,
|
||||
.name = "rtl8723e_pci",
|
||||
- .fw_name = "rtlwifi/rtl8723efw.bin",
|
||||
.ops = &rtl8723e_hal_ops,
|
||||
.mod_params = &rtl8723e_mod_params,
|
||||
.maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
|
||||
index 20b53f0..847644d 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
|
||||
@@ -91,6 +91,7 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw)
|
||||
struct rtl_priv *rtlpriv = rtl_priv(hw);
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
+ char *fw_name = "rtlwifi/rtl8723befw.bin";
|
||||
|
||||
rtl8723be_bt_reg_init(hw);
|
||||
rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
|
||||
@@ -184,8 +185,8 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
rtlpriv->max_fw_size = 0x8000;
|
||||
- pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
- err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
+ pr_info("Using firmware %s\n", fw_name);
|
||||
+ err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_fw_cb);
|
||||
if (err) {
|
||||
@@ -280,7 +281,6 @@ static const struct rtl_hal_cfg rtl8723be_hal_cfg = {
|
||||
.bar_id = 2,
|
||||
.write_readback = true,
|
||||
.name = "rtl8723be_pci",
|
||||
- .fw_name = "rtlwifi/rtl8723befw.bin",
|
||||
.ops = &rtl8723be_hal_ops,
|
||||
.mod_params = &rtl8723be_mod_params,
|
||||
.maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
|
||||
index 22f687b1..297938e 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
|
||||
@@ -93,6 +93,7 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
|
||||
struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
|
||||
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
|
||||
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
|
||||
+ char *fw_name, *wowlan_fw_name;
|
||||
|
||||
rtl8821ae_bt_reg_init(hw);
|
||||
rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
|
||||
@@ -203,17 +204,17 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
|
||||
}
|
||||
|
||||
if (rtlhal->hw_type == HARDWARE_TYPE_RTL8812AE) {
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8812aefw.bin";
|
||||
- rtlpriv->cfg->wowlan_fw_name = "rtlwifi/rtl8812aefw_wowlan.bin";
|
||||
+ fw_name = "rtlwifi/rtl8812aefw.bin";
|
||||
+ wowlan_fw_name = "rtlwifi/rtl8812aefw_wowlan.bin";
|
||||
} else {
|
||||
- rtlpriv->cfg->fw_name = "rtlwifi/rtl8821aefw.bin";
|
||||
- rtlpriv->cfg->wowlan_fw_name = "rtlwifi/rtl8821aefw_wowlan.bin";
|
||||
+ fw_name = "rtlwifi/rtl8821aefw.bin";
|
||||
+ wowlan_fw_name = "rtlwifi/rtl8821aefw_wowlan.bin";
|
||||
}
|
||||
|
||||
rtlpriv->max_fw_size = 0x8000;
|
||||
/*load normal firmware*/
|
||||
- pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
|
||||
- err = request_firmware_nowait(THIS_MODULE, 1, rtlpriv->cfg->fw_name,
|
||||
+ pr_info("Using firmware %s\n", fw_name);
|
||||
+ err = request_firmware_nowait(THIS_MODULE, 1, fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_fw_cb);
|
||||
if (err) {
|
||||
@@ -222,9 +223,9 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
|
||||
return 1;
|
||||
}
|
||||
/*load wowlan firmware*/
|
||||
- pr_info("Using firmware %s\n", rtlpriv->cfg->wowlan_fw_name);
|
||||
+ pr_info("Using firmware %s\n", wowlan_fw_name);
|
||||
err = request_firmware_nowait(THIS_MODULE, 1,
|
||||
- rtlpriv->cfg->wowlan_fw_name,
|
||||
+ wowlan_fw_name,
|
||||
rtlpriv->io.dev, GFP_KERNEL, hw,
|
||||
rtl_wowlan_fw_cb);
|
||||
if (err) {
|
||||
@@ -320,7 +321,6 @@ static const struct rtl_hal_cfg rtl8821ae_hal_cfg = {
|
||||
.bar_id = 2,
|
||||
.write_readback = true,
|
||||
.name = "rtl8821ae_pci",
|
||||
- .fw_name = "rtlwifi/rtl8821aefw.bin",
|
||||
.ops = &rtl8821ae_hal_ops,
|
||||
.mod_params = &rtl8821ae_mod_params,
|
||||
.maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
|
||||
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
|
||||
index 595f7d5..dafe486 100644
|
||||
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
|
||||
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
|
||||
@@ -2278,9 +2278,7 @@ struct rtl_hal_cfg {
|
||||
u8 bar_id;
|
||||
bool write_readback;
|
||||
char *name;
|
||||
- char *fw_name;
|
||||
char *alt_fw_name;
|
||||
- char *wowlan_fw_name;
|
||||
struct rtl_hal_ops *ops;
|
||||
struct rtl_mod_params *mod_params;
|
||||
struct rtl_hal_usbint_cfg *usb_interface_cfg;
|
||||
@@ -0,0 +1,111 @@
|
||||
diff --git a/drivers/nvme/host/scsi.c b/drivers/nvme/host/scsi.c
|
||||
index e947e298a737..44009105f8c8 100644
|
||||
--- a/drivers/nvme/host/scsi.c
|
||||
+++ b/drivers/nvme/host/scsi.c
|
||||
@@ -72,15 +72,6 @@ static int sg_version_num = 30534; /* 2 digits for each component */
|
||||
#define ALL_LUNS_RETURNED 0x02
|
||||
#define ALL_WELL_KNOWN_LUNS_RETURNED 0x01
|
||||
#define RESTRICTED_LUNS_RETURNED 0x00
|
||||
-#define NVME_POWER_STATE_START_VALID 0x00
|
||||
-#define NVME_POWER_STATE_ACTIVE 0x01
|
||||
-#define NVME_POWER_STATE_IDLE 0x02
|
||||
-#define NVME_POWER_STATE_STANDBY 0x03
|
||||
-#define NVME_POWER_STATE_LU_CONTROL 0x07
|
||||
-#define POWER_STATE_0 0
|
||||
-#define POWER_STATE_1 1
|
||||
-#define POWER_STATE_2 2
|
||||
-#define POWER_STATE_3 3
|
||||
#define DOWNLOAD_SAVE_ACTIVATE 0x05
|
||||
#define DOWNLOAD_SAVE_DEFER_ACTIVATE 0x0E
|
||||
#define ACTIVATE_DEFERRED_MICROCODE 0x0F
|
||||
@@ -1229,64 +1220,6 @@ static void nvme_trans_fill_read_cap(u8 *response, struct nvme_id_ns *id_ns,
|
||||
|
||||
/* Start Stop Unit Helper Functions */
|
||||
|
||||
-static int nvme_trans_power_state(struct nvme_ns *ns, struct sg_io_hdr *hdr,
|
||||
- u8 pc, u8 pcmod, u8 start)
|
||||
-{
|
||||
- int res;
|
||||
- int nvme_sc;
|
||||
- struct nvme_id_ctrl *id_ctrl;
|
||||
- int lowest_pow_st; /* max npss = lowest power consumption */
|
||||
- unsigned ps_desired = 0;
|
||||
-
|
||||
- nvme_sc = nvme_identify_ctrl(ns->ctrl, &id_ctrl);
|
||||
- res = nvme_trans_status_code(hdr, nvme_sc);
|
||||
- if (res)
|
||||
- return res;
|
||||
-
|
||||
- lowest_pow_st = max(POWER_STATE_0, (int)(id_ctrl->npss - 1));
|
||||
- kfree(id_ctrl);
|
||||
-
|
||||
- switch (pc) {
|
||||
- case NVME_POWER_STATE_START_VALID:
|
||||
- /* Action unspecified if POWER CONDITION MODIFIER != 0 */
|
||||
- if (pcmod == 0 && start == 0x1)
|
||||
- ps_desired = POWER_STATE_0;
|
||||
- if (pcmod == 0 && start == 0x0)
|
||||
- ps_desired = lowest_pow_st;
|
||||
- break;
|
||||
- case NVME_POWER_STATE_ACTIVE:
|
||||
- /* Action unspecified if POWER CONDITION MODIFIER != 0 */
|
||||
- if (pcmod == 0)
|
||||
- ps_desired = POWER_STATE_0;
|
||||
- break;
|
||||
- case NVME_POWER_STATE_IDLE:
|
||||
- /* Action unspecified if POWER CONDITION MODIFIER != [0,1,2] */
|
||||
- if (pcmod == 0x0)
|
||||
- ps_desired = POWER_STATE_1;
|
||||
- else if (pcmod == 0x1)
|
||||
- ps_desired = POWER_STATE_2;
|
||||
- else if (pcmod == 0x2)
|
||||
- ps_desired = POWER_STATE_3;
|
||||
- break;
|
||||
- case NVME_POWER_STATE_STANDBY:
|
||||
- /* Action unspecified if POWER CONDITION MODIFIER != [0,1] */
|
||||
- if (pcmod == 0x0)
|
||||
- ps_desired = max(POWER_STATE_0, (lowest_pow_st - 2));
|
||||
- else if (pcmod == 0x1)
|
||||
- ps_desired = max(POWER_STATE_0, (lowest_pow_st - 1));
|
||||
- break;
|
||||
- case NVME_POWER_STATE_LU_CONTROL:
|
||||
- default:
|
||||
- res = nvme_trans_completion(hdr, SAM_STAT_CHECK_CONDITION,
|
||||
- ILLEGAL_REQUEST, SCSI_ASC_INVALID_CDB,
|
||||
- SCSI_ASCQ_CAUSE_NOT_REPORTABLE);
|
||||
- break;
|
||||
- }
|
||||
- nvme_sc = nvme_set_features(ns->ctrl, NVME_FEAT_POWER_MGMT, ps_desired, 0,
|
||||
- NULL);
|
||||
- return nvme_trans_status_code(hdr, nvme_sc);
|
||||
-}
|
||||
-
|
||||
static int nvme_trans_send_activate_fw_cmd(struct nvme_ns *ns, struct sg_io_hdr *hdr,
|
||||
u8 buffer_id)
|
||||
{
|
||||
@@ -2235,11 +2168,10 @@ static int nvme_trans_synchronize_cache(struct nvme_ns *ns,
|
||||
static int nvme_trans_start_stop(struct nvme_ns *ns, struct sg_io_hdr *hdr,
|
||||
u8 *cmd)
|
||||
{
|
||||
- u8 immed, pcmod, pc, no_flush, start;
|
||||
+ u8 immed, pcmod, no_flush, start;
|
||||
|
||||
immed = cmd[1] & 0x01;
|
||||
pcmod = cmd[3] & 0x0f;
|
||||
- pc = (cmd[4] & 0xf0) >> 4;
|
||||
no_flush = cmd[4] & 0x04;
|
||||
start = cmd[4] & 0x01;
|
||||
|
||||
@@ -2254,8 +2186,8 @@ static int nvme_trans_start_stop(struct nvme_ns *ns, struct sg_io_hdr *hdr,
|
||||
if (res)
|
||||
return res;
|
||||
}
|
||||
- /* Setup the expected power state transition */
|
||||
- return nvme_trans_power_state(ns, hdr, pc, pcmod, start);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.7.4
|
||||
@@ -0,0 +1,107 @@
|
||||
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
|
||||
index 2feacc70bf61..b92a7f767bfc 100644
|
||||
--- a/drivers/nvme/host/core.c
|
||||
+++ b/drivers/nvme/host/core.c
|
||||
@@ -597,7 +597,7 @@ int nvme_identify_ns(struct nvme_ctrl *dev, unsigned nsid,
|
||||
}
|
||||
|
||||
int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid,
|
||||
- dma_addr_t dma_addr, u32 *result)
|
||||
+ void *buffer, size_t buflen, u32 *result)
|
||||
{
|
||||
struct nvme_command c;
|
||||
struct nvme_completion cqe;
|
||||
@@ -606,10 +606,9 @@ int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid,
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.features.opcode = nvme_admin_get_features;
|
||||
c.features.nsid = cpu_to_le32(nsid);
|
||||
- c.features.dptr.prp1 = cpu_to_le64(dma_addr);
|
||||
c.features.fid = cpu_to_le32(fid);
|
||||
|
||||
- ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe, NULL, 0, 0,
|
||||
+ ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe, buffer, buflen, 0,
|
||||
NVME_QID_ANY, 0, 0);
|
||||
if (ret >= 0 && result)
|
||||
*result = le32_to_cpu(cqe.result);
|
||||
@@ -617,7 +616,7 @@ int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid,
|
||||
}
|
||||
|
||||
int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
|
||||
- dma_addr_t dma_addr, u32 *result)
|
||||
+ void *buffer, size_t buflen, u32 *result)
|
||||
{
|
||||
struct nvme_command c;
|
||||
struct nvme_completion cqe;
|
||||
@@ -625,12 +624,11 @@ int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
|
||||
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.features.opcode = nvme_admin_set_features;
|
||||
- c.features.dptr.prp1 = cpu_to_le64(dma_addr);
|
||||
c.features.fid = cpu_to_le32(fid);
|
||||
c.features.dword11 = cpu_to_le32(dword11);
|
||||
|
||||
- ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe, NULL, 0, 0,
|
||||
- NVME_QID_ANY, 0, 0);
|
||||
+ ret = __nvme_submit_sync_cmd(dev->admin_q, &c, &cqe,
|
||||
+ buffer, buflen, 0, NVME_QID_ANY, 0, 0);
|
||||
if (ret >= 0 && result)
|
||||
*result = le32_to_cpu(cqe.result);
|
||||
return ret;
|
||||
@@ -664,7 +662,7 @@ int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count)
|
||||
u32 result;
|
||||
int status, nr_io_queues;
|
||||
|
||||
- status = nvme_set_features(ctrl, NVME_FEAT_NUM_QUEUES, q_count, 0,
|
||||
+ status = nvme_set_features(ctrl, NVME_FEAT_NUM_QUEUES, q_count, NULL, 0,
|
||||
&result);
|
||||
if (status < 0)
|
||||
return status;
|
||||
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
|
||||
index ab18b78102bf..c2151761ec5f 100644
|
||||
--- a/drivers/nvme/host/nvme.h
|
||||
+++ b/drivers/nvme/host/nvme.h
|
||||
@@ -292,9 +292,9 @@ int nvme_identify_ns(struct nvme_ctrl *dev, unsigned nsid,
|
||||
struct nvme_id_ns **id);
|
||||
int nvme_get_log_page(struct nvme_ctrl *dev, struct nvme_smart_log **log);
|
||||
int nvme_get_features(struct nvme_ctrl *dev, unsigned fid, unsigned nsid,
|
||||
- dma_addr_t dma_addr, u32 *result);
|
||||
+ void *buffer, size_t buflen, u32 *result);
|
||||
int nvme_set_features(struct nvme_ctrl *dev, unsigned fid, unsigned dword11,
|
||||
- dma_addr_t dma_addr, u32 *result);
|
||||
+ void *buffer, size_t buflen, u32 *result);
|
||||
int nvme_set_queue_count(struct nvme_ctrl *ctrl, int *count);
|
||||
void nvme_start_keep_alive(struct nvme_ctrl *ctrl);
|
||||
void nvme_stop_keep_alive(struct nvme_ctrl *ctrl);
|
||||
diff --git a/drivers/nvme/host/scsi.c b/drivers/nvme/host/scsi.c
|
||||
index 44009105f8c8..c2a0a1c7d05d 100644
|
||||
--- a/drivers/nvme/host/scsi.c
|
||||
+++ b/drivers/nvme/host/scsi.c
|
||||
@@ -906,7 +906,7 @@ static int nvme_trans_log_temperature(struct nvme_ns *ns, struct sg_io_hdr *hdr,
|
||||
kfree(smart_log);
|
||||
|
||||
/* Get Features for Temp Threshold */
|
||||
- res = nvme_get_features(ns->ctrl, NVME_FEAT_TEMP_THRESH, 0, 0,
|
||||
+ res = nvme_get_features(ns->ctrl, NVME_FEAT_TEMP_THRESH, 0, NULL, 0,
|
||||
&feature_resp);
|
||||
if (res != NVME_SC_SUCCESS)
|
||||
temp_c_thresh = LOG_TEMP_UNKNOWN;
|
||||
@@ -1039,7 +1039,7 @@ static int nvme_trans_fill_caching_page(struct nvme_ns *ns,
|
||||
if (len < MODE_PAGE_CACHING_LEN)
|
||||
return -EINVAL;
|
||||
|
||||
- nvme_sc = nvme_get_features(ns->ctrl, NVME_FEAT_VOLATILE_WC, 0, 0,
|
||||
+ nvme_sc = nvme_get_features(ns->ctrl, NVME_FEAT_VOLATILE_WC, 0, NULL, 0,
|
||||
&feature_resp);
|
||||
res = nvme_trans_status_code(hdr, nvme_sc);
|
||||
if (res)
|
||||
@@ -1328,7 +1328,7 @@ static int nvme_trans_modesel_get_mp(struct nvme_ns *ns, struct sg_io_hdr *hdr,
|
||||
case MODE_PAGE_CACHING:
|
||||
dword11 = ((mode_page[2] & CACHING_MODE_PAGE_WCE_MASK) ? 1 : 0);
|
||||
nvme_sc = nvme_set_features(ns->ctrl, NVME_FEAT_VOLATILE_WC,
|
||||
- dword11, 0, NULL);
|
||||
+ dword11, NULL, 0, NULL);
|
||||
res = nvme_trans_status_code(hdr, nvme_sc);
|
||||
break;
|
||||
case MODE_PAGE_CONTROL:
|
||||
--
|
||||
2.7.4
|
||||
@@ -0,0 +1,264 @@
|
||||
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
|
||||
index b92a7f767bfc..a143c72c3d0d 100644
|
||||
--- a/drivers/nvme/host/core.c
|
||||
+++ b/drivers/nvme/host/core.c
|
||||
@@ -56,6 +56,11 @@ EXPORT_SYMBOL_GPL(nvme_max_retries);
|
||||
static int nvme_char_major;
|
||||
module_param(nvme_char_major, int, 0);
|
||||
|
||||
+static unsigned long default_ps_max_latency_us = 25000;
|
||||
+module_param(default_ps_max_latency_us, ulong, 0644);
|
||||
+MODULE_PARM_DESC(ps_max_latency_us,
|
||||
+ "default max power saving latency; overridden per device in sysfs");
|
||||
+
|
||||
static LIST_HEAD(nvme_ctrl_list);
|
||||
static DEFINE_SPINLOCK(dev_list_lock);
|
||||
|
||||
@@ -1205,6 +1210,98 @@ static void nvme_set_queue_limits(struct nvme_ctrl *ctrl,
|
||||
blk_queue_write_cache(q, vwc, vwc);
|
||||
}
|
||||
|
||||
+static void nvme_configure_apst(struct nvme_ctrl *ctrl)
|
||||
+{
|
||||
+ /*
|
||||
+ * APST (Autonomous Power State Transition) lets us program a
|
||||
+ * table of power state transitions that the controller will
|
||||
+ * perform automatically. We configure it with a simple
|
||||
+ * heuristic: we are willing to spend at most 2% of the time
|
||||
+ * transitioning between power states. Therefore, when running
|
||||
+ * in any given state, we will enter the next lower-power
|
||||
+ * non-operational state after waiting 100 * (enlat + exlat)
|
||||
+ * microseconds, as long as that state's total latency is under
|
||||
+ * the requested maximum latency.
|
||||
+ *
|
||||
+ * We will not autonomously enter any non-operational state for
|
||||
+ * which the total latency exceeds ps_max_latency_us. Users
|
||||
+ * can set ps_max_latency_us to zero to turn off APST.
|
||||
+ */
|
||||
+
|
||||
+ unsigned apste;
|
||||
+ struct nvme_feat_auto_pst *table;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!ctrl->apsta)
|
||||
+ return; /* APST isn't supported. */
|
||||
+
|
||||
+ if (ctrl->npss > 31) {
|
||||
+ dev_warn(ctrl->device, "NPSS is invalid; not using APST\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ table = kzalloc(sizeof(*table), GFP_KERNEL);
|
||||
+ if (!table)
|
||||
+ return;
|
||||
+
|
||||
+ if (ctrl->ps_max_latency_us == 0) {
|
||||
+ /* Turn off APST. */
|
||||
+ apste = 0;
|
||||
+ } else {
|
||||
+ __le64 target = cpu_to_le64(0);
|
||||
+ int state;
|
||||
+
|
||||
+ /*
|
||||
+ * Walk through all states from lowest- to highest-power.
|
||||
+ * According to the spec, lower-numbered states use more
|
||||
+ * power. NPSS, despite the name, is the index of the
|
||||
+ * lowest-power state, not the number of states.
|
||||
+ */
|
||||
+ for (state = (int)ctrl->npss; state >= 0; state--) {
|
||||
+ u64 total_latency_us, transition_ms;
|
||||
+
|
||||
+ if (target)
|
||||
+ table->entries[state] = target;
|
||||
+
|
||||
+ /*
|
||||
+ * Is this state a useful non-operational state for
|
||||
+ * higher-power states to autonomously transition to?
|
||||
+ */
|
||||
+ if (!(ctrl->psd[state].flags & 2))
|
||||
+ continue; /* It's an operational state. */
|
||||
+
|
||||
+ total_latency_us =
|
||||
+ (u64)cpu_to_le32(ctrl->psd[state].entry_lat) +
|
||||
+ + cpu_to_le32(ctrl->psd[state].exit_lat);
|
||||
+ if (total_latency_us > ctrl->ps_max_latency_us)
|
||||
+ continue;
|
||||
+
|
||||
+ /*
|
||||
+ * This state is good. Use it as the APST idle
|
||||
+ * target for higher power states.
|
||||
+ */
|
||||
+ transition_ms = total_latency_us + 19;
|
||||
+ do_div(transition_ms, 20);
|
||||
+ if (transition_ms >= (1 << 24))
|
||||
+ transition_ms = (1 << 24);
|
||||
+
|
||||
+ target = cpu_to_le64((state << 3) |
|
||||
+ (transition_ms << 8));
|
||||
+ }
|
||||
+
|
||||
+ apste = 1;
|
||||
+ }
|
||||
+
|
||||
+ ret = nvme_set_features(ctrl, NVME_FEAT_AUTO_PST, apste,
|
||||
+ table, sizeof(*table), NULL);
|
||||
+ if (ret)
|
||||
+ dev_err(ctrl->device, "failed to set APST feature (%d)\n", ret);
|
||||
+
|
||||
+ kfree(table);
|
||||
+}
|
||||
+
|
||||
+static struct attribute_group nvme_dev_dynamic_attrs_group;
|
||||
+
|
||||
/*
|
||||
* Initialize the cached copies of the Identify data and various controller
|
||||
* register in our nvme_ctrl structure. This should be called as soon as
|
||||
@@ -1271,6 +1368,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
|
||||
ctrl->sgls = le32_to_cpu(id->sgls);
|
||||
ctrl->kas = le16_to_cpu(id->kas);
|
||||
|
||||
+ ctrl->npss = id->npss;
|
||||
+ ctrl->apsta = id->apsta;
|
||||
+ memcpy(ctrl->psd, id->psd, sizeof(ctrl->psd));
|
||||
+
|
||||
if (ctrl->ops->is_fabrics) {
|
||||
ctrl->icdoff = le16_to_cpu(id->icdoff);
|
||||
ctrl->ioccsz = le32_to_cpu(id->ioccsz);
|
||||
@@ -1294,6 +1395,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
|
||||
}
|
||||
|
||||
kfree(id);
|
||||
+
|
||||
+ nvme_configure_apst(ctrl);
|
||||
+
|
||||
+ sysfs_update_group(&ctrl->device->kobj, &nvme_dev_dynamic_attrs_group);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nvme_init_identify);
|
||||
@@ -1564,6 +1669,41 @@ static ssize_t nvme_sysfs_show_address(struct device *dev,
|
||||
}
|
||||
static DEVICE_ATTR(address, S_IRUGO, nvme_sysfs_show_address, NULL);
|
||||
|
||||
+static ssize_t nvme_sysfs_show_ps_max_latency_us(
|
||||
+ struct device *dev,
|
||||
+ struct device_attribute *attr,
|
||||
+ char *buf)
|
||||
+{
|
||||
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
|
||||
+
|
||||
+ return snprintf(buf, PAGE_SIZE, "%llu\n", ctrl->ps_max_latency_us);
|
||||
+}
|
||||
+
|
||||
+static ssize_t nvme_sysfs_store_ps_max_latency_us(
|
||||
+ struct device *dev,
|
||||
+ struct device_attribute *attr,
|
||||
+ const char *buf, size_t size)
|
||||
+{
|
||||
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
|
||||
+ int ret;
|
||||
+ u64 val;
|
||||
+
|
||||
+ ret = kstrtoull(buf, 10, &val);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (ctrl->ps_max_latency_us != val) {
|
||||
+ ctrl->ps_max_latency_us = val;
|
||||
+ nvme_configure_apst(ctrl);
|
||||
+ }
|
||||
+
|
||||
+ return size;
|
||||
+}
|
||||
+
|
||||
+static DEVICE_ATTR(ps_max_latency_us, 0644,
|
||||
+ nvme_sysfs_show_ps_max_latency_us,
|
||||
+ nvme_sysfs_store_ps_max_latency_us);
|
||||
+
|
||||
static struct attribute *nvme_dev_attrs[] = {
|
||||
&dev_attr_reset_controller.attr,
|
||||
&dev_attr_rescan_controller.attr,
|
||||
@@ -1605,8 +1745,33 @@ static struct attribute_group nvme_dev_attrs_group = {
|
||||
.is_visible = nvme_dev_attrs_are_visible,
|
||||
};
|
||||
|
||||
+static struct attribute *nvme_dev_dynamic_attrs[] = {
|
||||
+ &dev_attr_ps_max_latency_us.attr,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+static umode_t nvme_dev_dynamic_attrs_are_visible(struct kobject *kobj,
|
||||
+ struct attribute *a, int n)
|
||||
+{
|
||||
+ struct device *dev = container_of(kobj, struct device, kobj);
|
||||
+ struct nvme_ctrl *ctrl = dev_get_drvdata(dev);
|
||||
+
|
||||
+ if (a == &dev_attr_ps_max_latency_us.attr) {
|
||||
+ if (!ctrl->apsta)
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return a->mode;
|
||||
+}
|
||||
+
|
||||
+static struct attribute_group nvme_dev_dynamic_attrs_group = {
|
||||
+ .attrs = nvme_dev_dynamic_attrs,
|
||||
+ .is_visible = nvme_dev_dynamic_attrs_are_visible,
|
||||
+};
|
||||
+
|
||||
static const struct attribute_group *nvme_dev_attr_groups[] = {
|
||||
&nvme_dev_attrs_group,
|
||||
+ &nvme_dev_dynamic_attrs_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -1991,6 +2156,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
|
||||
ctrl->quirks = quirks;
|
||||
INIT_WORK(&ctrl->scan_work, nvme_scan_work);
|
||||
INIT_WORK(&ctrl->async_event_work, nvme_async_event_work);
|
||||
+ ctrl->ps_max_latency_us = default_ps_max_latency_us;
|
||||
|
||||
ret = nvme_set_instance(ctrl);
|
||||
if (ret)
|
||||
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
|
||||
index c2151761ec5f..16d51006afc0 100644
|
||||
--- a/drivers/nvme/host/nvme.h
|
||||
+++ b/drivers/nvme/host/nvme.h
|
||||
@@ -129,13 +129,19 @@ struct nvme_ctrl {
|
||||
u32 vs;
|
||||
u32 sgls;
|
||||
u16 kas;
|
||||
+ u8 npss;
|
||||
+ u8 apsta;
|
||||
unsigned int kato;
|
||||
bool subsystem;
|
||||
unsigned long quirks;
|
||||
+ struct nvme_id_power_state psd[32];
|
||||
struct work_struct scan_work;
|
||||
struct work_struct async_event_work;
|
||||
struct delayed_work ka_work;
|
||||
|
||||
+ /* Power saving configuration */
|
||||
+ u64 ps_max_latency_us;
|
||||
+
|
||||
/* Fabrics only */
|
||||
u16 sqsize;
|
||||
u32 ioccsz;
|
||||
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
|
||||
index d8b37bab2887..a76237dac4b0 100644
|
||||
--- a/include/linux/nvme.h
|
||||
+++ b/include/linux/nvme.h
|
||||
@@ -543,6 +543,12 @@ struct nvme_dsm_range {
|
||||
__le64 slba;
|
||||
};
|
||||
|
||||
+/* Features */
|
||||
+
|
||||
+struct nvme_feat_auto_pst {
|
||||
+ __le64 entries[32];
|
||||
+};
|
||||
+
|
||||
/* Admin commands */
|
||||
|
||||
enum nvme_admin_opcode {
|
||||
--
|
||||
2.7.4
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
|
||||
index 2d24813..498ded6 100644
|
||||
--- a/drivers/gpu/drm/i915/intel_pm.c
|
||||
+++ b/drivers/gpu/drm/i915/intel_pm.c
|
||||
@@ -2877,6 +2877,21 @@ skl_wm_plane_id(const struct intel_plane *plane)
|
||||
}
|
||||
|
||||
/*
|
||||
+ * FIXME: We still don't have the proper code detect if we need to apply the WA,
|
||||
+ * so assume we'll always need it in order to avoid underruns.
|
||||
+ */
|
||||
+static bool skl_needs_memory_bw_wa(struct intel_atomic_state *state)
|
||||
+{
|
||||
+ struct drm_i915_private *dev_priv = to_i915(state->base.dev);
|
||||
+
|
||||
+ if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) ||
|
||||
+ IS_KABYLAKE(dev_priv))
|
||||
+ return true;
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* SAGV dynamically adjusts the system agent voltage and clock frequencies
|
||||
* depending on power and performance requirements. The display engine access
|
||||
* to system memory is blocked during the adjustment time. Because of the
|
||||
@@ -2979,9 +2994,10 @@ bool skl_can_enable_sagv(struct drm_atomic_state *state)
|
||||
struct drm_device *dev = state->dev;
|
||||
struct drm_i915_private *dev_priv = to_i915(dev);
|
||||
struct intel_atomic_state *intel_state = to_intel_atomic_state(state);
|
||||
- struct drm_crtc *crtc;
|
||||
+ struct intel_crtc *crtc;
|
||||
+ struct intel_plane *plane;
|
||||
enum pipe pipe;
|
||||
- int level, plane;
|
||||
+ int level, id, latency;
|
||||
|
||||
/*
|
||||
* SKL workaround: bspec recommends we disable the SAGV when we have
|
||||
@@ -2996,27 +3012,35 @@ bool skl_can_enable_sagv(struct drm_atomic_state *state)
|
||||
|
||||
/* Since we're now guaranteed to only have one active CRTC... */
|
||||
pipe = ffs(intel_state->active_crtcs) - 1;
|
||||
- crtc = dev_priv->pipe_to_crtc_mapping[pipe];
|
||||
+ crtc = to_intel_crtc(dev_priv->pipe_to_crtc_mapping[pipe]);
|
||||
|
||||
- if (crtc->state->mode.flags & DRM_MODE_FLAG_INTERLACE)
|
||||
+ if (crtc->base.state->adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE)
|
||||
return false;
|
||||
+ for_each_intel_plane_on_crtc(dev, crtc, plane) {
|
||||
+ id = skl_wm_plane_id(plane);
|
||||
|
||||
- for_each_plane(dev_priv, pipe, plane) {
|
||||
/* Skip this plane if it's not enabled */
|
||||
- if (intel_state->wm_results.plane[pipe][plane][0] == 0)
|
||||
+ if (intel_state->wm_results.plane[pipe][id][0] == 0)
|
||||
continue;
|
||||
|
||||
/* Find the highest enabled wm level for this plane */
|
||||
for (level = ilk_wm_max_level(dev);
|
||||
- intel_state->wm_results.plane[pipe][plane][level] == 0; --level)
|
||||
+ intel_state->wm_results.plane[pipe][id][level] == 0; --level)
|
||||
{ }
|
||||
|
||||
+ latency = dev_priv->wm.skl_latency[level];
|
||||
+
|
||||
+ if (skl_needs_memory_bw_wa(intel_state) &&
|
||||
+ plane->base.state->fb->modifier[0] ==
|
||||
+ I915_FORMAT_MOD_X_TILED)
|
||||
+ latency += 15;
|
||||
+
|
||||
/*
|
||||
* If any of the planes on this pipe don't enable wm levels
|
||||
* that incur memory latencies higher then 30µs we can't enable
|
||||
* the SAGV
|
||||
*/
|
||||
- if (dev_priv->wm.skl_latency[level] < SKL_SAGV_BLOCK_TIME)
|
||||
+ if (latency < SKL_SAGV_BLOCK_TIME)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3546,12 +3570,18 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
|
||||
uint8_t cpp;
|
||||
uint32_t width = 0, height = 0;
|
||||
uint32_t plane_pixel_rate;
|
||||
+ struct intel_atomic_state *state =
|
||||
+ to_intel_atomic_state(cstate->base.state);
|
||||
+ bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state);
|
||||
|
||||
if (latency == 0 || !cstate->base.active || !intel_pstate->visible) {
|
||||
*enabled = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ if (apply_memory_bw_wa && fb->modifier[0] == I915_FORMAT_MOD_X_TILED)
|
||||
+ latency += 15;
|
||||
+
|
||||
width = drm_rect_width(&intel_pstate->src) >> 16;
|
||||
height = drm_rect_height(&intel_pstate->src) >> 16;
|
||||
|
||||
@@ -3593,6 +3623,9 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
|
||||
}
|
||||
}
|
||||
y_tile_minimum = plane_blocks_per_line * min_scanlines;
|
||||
+ if (apply_memory_bw_wa)
|
||||
+ y_tile_minimum *= 2;
|
||||
+
|
||||
selected_result = max(method2, y_tile_minimum);
|
||||
} else {
|
||||
if ((ddb_allocation / plane_blocks_per_line) >= 1)
|
||||
Reference in New Issue
Block a user