aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/4123-Fix-to-the-crash-observed-when-the-following-operati.patch
blob: 0b49c20ad0bbf7663faf26b22c85fc1998983f44 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
From 6e99456ad3089ecf55dcf73d8162defdc637fa88 Mon Sep 17 00:00:00 2001
From: Sudheesh Mavila <sudheesh.mavila@amd.com>
Date: Mon, 20 Aug 2018 00:18:38 +0530
Subject: [PATCH 4123/4131] Fix to the crash observed when the following
 operations are performed. write and read an i2c device from i2c1 and then
 i2c0 - works write to a device in i2c1 - crash happens because mp2 gives a
 wrong interrupt Write to MP2 device is performed but the interrupt received
 is for read completion

[  493.360134]  in write
[  493.362745] BUG: unable to handle kernel NULL pointer dereference at           (null)
[  493.370643] IP: [<ffffffffc0768181>] i2c_amd_read_completion+0x91/0xe0 [i2c_amd_platdrv]
[  493.378779] PGD 2f92ad067 [  493.381322] PUD 2c4243067
PMD 0 [  493.384596]
[  493.386107] Oops: 0002 [#1] SMP
[  493.389259] Modules linked in: i2c_amd_platdrv(E) marvell binfmt_misc nls_iso8859_1
pl2303 usbserial amd64_edac_mod edac_mce_amd edac_core snd_hda_codec_hdmi kvm irqbypass
snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm crct10dif_pclmul crc32_pclmul
ghash_clmulni_intel snd_seq_midi snd_seq_midi_event joydev input_leds aesni_intel snd_rawmidi snd_seq aes_x86_64 snd_seq_device snd_timer lrw snd_pci_acp3x snd gf128mul soundcore glue_helper i2c_amd_pci_mp2(E) ablk_helper cryptd shpchp i2c_designware_platform i2c_piix4 i2c_designware_core mac_hid parport_pc ppdev lp parport autofs4 amdkfd amd_iommu_v2 mmc_block hid_generic amdgpu chash i2c_algo_bit ttm drm_kms_helper syscopyarea sysfillrect sysimgblt usbhid fb_sys_fops ixgbe dca amd_xgbe ahci ptp drm sdhci_acpi hid libahci pps_core mdio video fjes sdhci
[  493.462798] CPU: 1 PID: 371 Comm: kworker/1:2 Tainted: G            E   4.9.0-2018_30_staging+ #71
[  493.471769] Hardware name: AMD Dibbler/Dibbler, BIOS RDB1106B 07/02/2018
[  493.478486] Workqueue: events amd_mp2_pci_work [i2c_amd_pci_mp2]
[  493.484526] task: ffff9f3d36bf2ac0 task.stack: ffffbdfac21e4000
[  493.490457] RIP: 0010:[<ffffffffc0768181>]  [<ffffffffc0768181>] i2c_amd_read_completion+0x91/0xe0 [i2c_amd_platdrv]
[  493.501014] RSP: 0018:ffffbdfac21e7e08  EFLAGS: 00010246
[  493.506337] RAX: 0000000000000001 RBX: ffff9f3d40998f00 RCX: 0000000000000000
[  493.513481] RDX: 0000000000000000 RSI: ffff9f3d3b46da10 RDI: 0000000000060001
[  493.520624] RBP: ffffbdfac21e7e08 R08: ffff9f3d39db1818 R09: 0000000000000000
[  493.527771] R10: 00000000ffffffff R11: 0000000000000eb5 R12: ffff9f3d43259180
[  493.534915] R13: ffff9f3d4325da00 R14: 0000000000000040 R15: ffff9f3d380054b0
[  493.542061] FS:  0000000000000000(0000) GS:ffff9f3d43240000(0000) knlGS:0000000000000000
[  493.550162] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  493.555918] CR2: 0000000000000000 CR3: 00000002fe0a7000 CR4: 00000000003406f0
[  493.563064] Stack:
[  493.565087]  ffffbdfac21e7e18 ffffffffc034d202 ffffbdfac21e7e58 ffffffffbb0a0641
[  493.572587]  0000000000000000 ffff9f3d43259180 ffff9f3d40998f30 0000000000000008
[  493.580096]  ffff9f3d432591a0 ffff9f3d40998f00 ffffbdfac21e7ec0 ffffffffbb0a09ab
[  493.587600] Call Trace:
[  493.590059]  [<ffffffffc034d202>] amd_mp2_pci_work+0xa2/0x130 [i2c_amd_pci_mp2]
[  493.597382]  [<ffffffffbb0a0641>] process_one_work+0x171/0x490
[  493.603225]  [<ffffffffbb0a09ab>] worker_thread+0x4b/0x500
[  493.608719]  [<ffffffffbb0a0960>] ? process_one_work+0x490/0x490
[  493.614736]  [<ffffffffbb0a0960>] ? process_one_work+0x490/0x490
[  493.620753]  [<ffffffffbb08a894>] ? SyS_exit_group+0x14/0x20
[  493.626424]  [<ffffffffbb0a6c5b>] kthread+0xdb/0x100
[  493.631401]  [<ffffffffbb0a6b80>] ? kthread_park+0x60/0x60
[  493.636900]  [<ffffffffbb003b83>] ? do_syscall_64+0x73/0xe0
[  493.642486]  [<ffffffffbb874774>] ret_from_fork+0x44/0x70
[  493.647894] Code: 03 f3 48 a5 31 d2 49 8d b8 68 04 00 00 66 41 89 90 92 04 00 00 e8 10 2f 96 fa 31 c0 5d c3 a8 04 75 46 85 c0 74 de 0f b6 16 a8 02 <88> 11 74 d5 89 c2 0f b7 44 16 fe 66 89 44 11 fe eb c7 83 f8 08
[  493.668399] RIP  [<ffffffffc0768181>] i2c_amd_read_completion+0x91/0xe0 [i2c_amd_platdrv]
[  493.676623]  RSP <ffffbdfac21e7e08>
[  493.680125] CR2: 0000000000000000
[  493.685840] ---[ end trace 7505e21302a270d5 ]---
[  493.690480] BUG: unable to handle kernel paging request at 00000000ee1d23ba
[  493.697502] IP:[  493.697968]  in write
[  493.702151]  [<ffffffffbb0ca68e>] __wake_up_common+0x2e/0x90
[  493.708523] PGD 2f92ad067 [  493.711069] PUD 0
[  493.713785]
[  493.715961] Oops: 0000 [#2] SMP

Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
---
 drivers/i2c/busses/i2c-amd-pci-mp2.c | 50 +++++++++++++++++++++++++-----------
 drivers/i2c/busses/i2c-amd-pci-mp2.h |  2 +-
 2 files changed, 36 insertions(+), 16 deletions(-)

diff --git a/drivers/i2c/busses/i2c-amd-pci-mp2.c b/drivers/i2c/busses/i2c-amd-pci-mp2.c
index e8c58c7..d313435 100644
--- a/drivers/i2c/busses/i2c-amd-pci-mp2.c
+++ b/drivers/i2c/busses/i2c-amd-pci-mp2.c
@@ -76,6 +76,7 @@ int amd_mp2_connect(struct pci_dev *dev,
 	dev_dbg(ndev_dev(privdata), "%s addr: %x id: %d\n", __func__,
 		connect_cfg.dev_addr, connect_cfg.bus_id);
 
+	privdata->requested[connect_cfg.bus_id] = true;
 	i2c_cmd_base.ul = 0;
 	i2c_cmd_base.s.i2c_cmd = i2c_enable;
 	i2c_cmd_base.s.bus_id = connect_cfg.bus_id;
@@ -99,11 +100,12 @@ int amd_mp2_read(struct pci_dev *dev, struct i2c_read_config read_cfg)
 {
 	struct amd_mp2_dev *privdata = pci_get_drvdata(dev);
 	union i2c_cmd_base i2c_cmd_base;
-
+	int busid = read_cfg.bus_id;
+	
 	dev_dbg(ndev_dev(privdata), "%s addr: %x id: %d\n", __func__,
 		read_cfg.dev_addr, read_cfg.bus_id);
 
-	privdata->requested = true;
+	privdata->requested[busid] = true;
 	i2c_cmd_base.ul = 0;
 	i2c_cmd_base.s.i2c_cmd = i2c_read;
 	i2c_cmd_base.s.dev_addr = read_cfg.dev_addr;
@@ -166,8 +168,10 @@ int amd_mp2_write(struct pci_dev *dev, struct i2c_write_config write_cfg)
 	struct amd_mp2_dev *privdata = pci_get_drvdata(dev);
 	union i2c_cmd_base i2c_cmd_base;
 	int i = 0;
+	int busid = write_cfg.bus_id;
 
-	privdata->requested = true;
+	privdata->requested[busid] = true;
+	
 	dev_dbg(ndev_dev(privdata), "%s addr: %x id: %d\n", __func__,
 		write_cfg.dev_addr, write_cfg.bus_id);
 
@@ -292,31 +296,46 @@ static irqreturn_t amd_mp2_irq_isr(int irq, void *dev)
 {
 	struct amd_mp2_dev *privdata = dev;
 	u32 val = 0;
+	int busid = i2c_bus_max;
 	unsigned long  flags;
 
+
+	if (!privdata->ops) {
+		writel(0, privdata->mmio + AMD_P2C_MSG_INTEN);
+		return IRQ_HANDLED;
+	}
 	raw_spin_lock_irqsave(&privdata->lock, flags);
 	val = readl(privdata->mmio + AMD_P2C_MSG1);
 	if (val != 0) {
 		writel(0, privdata->mmio + AMD_P2C_MSG_INTEN);
-		privdata->eventval.base.ul = val;
-	} else {
+		busid = i2c_bus_0;
+
+		if (privdata->requested[i2c_bus_0] ) {
+			privdata->eventval.base.ul = val;
+			privdata->requested[i2c_bus_0] = false;
+			raw_spin_unlock_irqrestore(&privdata->lock, flags);
+			schedule_delayed_work(&privdata->work, 0);
+			return IRQ_HANDLED;
+		}
+	} 
+
 		val = readl(privdata->mmio + AMD_P2C_MSG2);
 		if (val != 0) {
 			writel(0, privdata->mmio + AMD_P2C_MSG_INTEN);
+		busid = i2c_bus_1;
+		if (privdata->requested[i2c_bus_1] ) {
 			privdata->eventval.base.ul = val;
+			privdata->requested[i2c_bus_1] = false;
+			raw_spin_unlock_irqrestore(&privdata->lock, flags);
+			schedule_delayed_work(&privdata->work, 0);
+			return IRQ_HANDLED;
 		}
 	}
 
+	if(busid == i2c_bus_max) {
+		writel(0, privdata->mmio + AMD_P2C_MSG_INTEN);
+	}
 	raw_spin_unlock_irqrestore(&privdata->lock, flags);
-	if (!privdata->ops)
-		return IRQ_NONE;
-
-	if (!privdata->requested)
-		return IRQ_HANDLED;
-
-	privdata->requested = false;
-	schedule_delayed_work(&privdata->work, 0);
-
 	return IRQ_HANDLED;
 }
 
@@ -495,7 +514,8 @@ static int amd_mp2_pci_init(struct amd_mp2_dev *privdata, struct pci_dev *pdev)
 	/* Try to set up intx irq */
 	pci_intx(pdev, 1);
 	privdata->eventval.buf = NULL;
-	privdata->requested = false;
+	privdata->requested[i2c_bus_0] = false;
+	privdata->requested[i2c_bus_1] = false;
 	raw_spin_lock_init(&privdata->lock);
 	rc = request_irq(pdev->irq, amd_mp2_irq_isr, IRQF_SHARED, "mp2_irq_isr",
 			 privdata);
diff --git a/drivers/i2c/busses/i2c-amd-pci-mp2.h b/drivers/i2c/busses/i2c-amd-pci-mp2.h
index d4b343a..8fef977 100644
--- a/drivers/i2c/busses/i2c-amd-pci-mp2.h
+++ b/drivers/i2c/busses/i2c-amd-pci-mp2.h
@@ -233,7 +233,7 @@ struct amd_mp2_dev {
 	const struct amd_i2c_pci_ops *ops;
 	struct delayed_work work;
 	u8 i2c_dev_id;
-	bool	requested;
+	bool	requested[i2c_bus_max];
 	raw_spinlock_t lock;
 };
 
-- 
2.7.4