hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/hid/intel-ish-hid/ipc/pci-ish.c
....@@ -1,16 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * PCI glue for ISHTP provider device (ISH) driver
34 *
45 * Copyright (c) 2014-2016, Intel Corporation.
5
- *
6
- * This program is free software; you can redistribute it and/or modify it
7
- * under the terms and conditions of the GNU General Public License,
8
- * version 2, as published by the Free Software Foundation.
9
- *
10
- * This program is distributed in the hope it will be useful, but WITHOUT
11
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13
- * more details.
146 */
157
168 #include <linux/module.h>
....@@ -22,6 +14,7 @@
2214 #include <linux/types.h>
2315 #include <linux/pci.h>
2416 #include <linux/sched.h>
17
+#include <linux/suspend.h>
2518 #include <linux/interrupt.h>
2619 #include <linux/workqueue.h>
2720 #define CREATE_TRACE_POINTS
....@@ -40,6 +33,10 @@
4033 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CNL_H_DEVICE_ID)},
4134 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ICL_MOBILE_DEVICE_ID)},
4235 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)},
36
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CML_LP_DEVICE_ID)},
37
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CMP_H_DEVICE_ID)},
38
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)},
39
+ {PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_LP_DEVICE_ID)},
4340 {0, }
4441 };
4542 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
....@@ -104,6 +101,16 @@
104101 {}
105102 };
106103
104
+static inline bool ish_should_enter_d0i3(struct pci_dev *pdev)
105
+{
106
+ return !pm_suspend_via_firmware() || pdev->device == CHV_DEVICE_ID;
107
+}
108
+
109
+static inline bool ish_should_leave_d0i3(struct pci_dev *pdev)
110
+{
111
+ return !pm_resume_via_firmware() || pdev->device == CHV_DEVICE_ID;
112
+}
113
+
107114 /**
108115 * ish_probe() - PCI driver probe callback
109116 * @pdev: pci device
....@@ -115,18 +122,20 @@
115122 */
116123 static int ish_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
117124 {
118
- struct ishtp_device *dev;
125
+ int ret;
119126 struct ish_hw *hw;
120
- int ret;
127
+ unsigned long irq_flag = 0;
128
+ struct ishtp_device *ishtp;
129
+ struct device *dev = &pdev->dev;
121130
122131 /* Check for invalid platforms for ISH support */
123132 if (pci_dev_present(ish_invalid_pci_ids))
124133 return -ENODEV;
125134
126135 /* enable pci dev */
127
- ret = pci_enable_device(pdev);
136
+ ret = pcim_enable_device(pdev);
128137 if (ret) {
129
- dev_err(&pdev->dev, "ISH: Failed to enable PCI device\n");
138
+ dev_err(dev, "ISH: Failed to enable PCI device\n");
130139 return ret;
131140 }
132141
....@@ -134,65 +143,47 @@
134143 pci_set_master(pdev);
135144
136145 /* pci request regions for ISH driver */
137
- ret = pci_request_regions(pdev, KBUILD_MODNAME);
146
+ ret = pcim_iomap_regions(pdev, 1 << 0, KBUILD_MODNAME);
138147 if (ret) {
139
- dev_err(&pdev->dev, "ISH: Failed to get PCI regions\n");
140
- goto disable_device;
148
+ dev_err(dev, "ISH: Failed to get PCI regions\n");
149
+ return ret;
141150 }
142151
143152 /* allocates and initializes the ISH dev structure */
144
- dev = ish_dev_init(pdev);
145
- if (!dev) {
153
+ ishtp = ish_dev_init(pdev);
154
+ if (!ishtp) {
146155 ret = -ENOMEM;
147
- goto release_regions;
156
+ return ret;
148157 }
149
- hw = to_ish_hw(dev);
150
- dev->print_log = ish_event_tracer;
158
+ hw = to_ish_hw(ishtp);
159
+ ishtp->print_log = ish_event_tracer;
151160
152161 /* mapping IO device memory */
153
- hw->mem_addr = pci_iomap(pdev, 0, 0);
154
- if (!hw->mem_addr) {
155
- dev_err(&pdev->dev, "ISH: mapping I/O range failure\n");
156
- ret = -ENOMEM;
157
- goto free_device;
158
- }
159
-
160
- dev->pdev = pdev;
161
-
162
- pdev->dev_flags |= PCI_DEV_FLAGS_NO_D3;
162
+ hw->mem_addr = pcim_iomap_table(pdev)[0];
163
+ ishtp->pdev = pdev;
163164
164165 /* request and enable interrupt */
165
- ret = request_irq(pdev->irq, ish_irq_handler, IRQF_SHARED,
166
- KBUILD_MODNAME, dev);
166
+ ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
167
+ if (!pdev->msi_enabled && !pdev->msix_enabled)
168
+ irq_flag = IRQF_SHARED;
169
+
170
+ ret = devm_request_irq(dev, pdev->irq, ish_irq_handler,
171
+ irq_flag, KBUILD_MODNAME, ishtp);
167172 if (ret) {
168
- dev_err(&pdev->dev, "ISH: request IRQ failure (%d)\n",
169
- pdev->irq);
170
- goto free_device;
173
+ dev_err(dev, "ISH: request IRQ %d failed\n", pdev->irq);
174
+ return ret;
171175 }
172176
173
- dev_set_drvdata(dev->devc, dev);
177
+ dev_set_drvdata(ishtp->devc, ishtp);
174178
175
- init_waitqueue_head(&dev->suspend_wait);
176
- init_waitqueue_head(&dev->resume_wait);
179
+ init_waitqueue_head(&ishtp->suspend_wait);
180
+ init_waitqueue_head(&ishtp->resume_wait);
177181
178
- ret = ish_init(dev);
182
+ ret = ish_init(ishtp);
179183 if (ret)
180
- goto free_irq;
184
+ return ret;
181185
182186 return 0;
183
-
184
-free_irq:
185
- free_irq(pdev->irq, dev);
186
-free_device:
187
- pci_iounmap(pdev, hw->mem_addr);
188
-release_regions:
189
- pci_release_regions(pdev);
190
-disable_device:
191
- pci_clear_master(pdev);
192
- pci_disable_device(pdev);
193
- dev_err(&pdev->dev, "ISH: PCI driver initialization failed.\n");
194
-
195
- return ret;
196187 }
197188
198189 /**
....@@ -204,16 +195,9 @@
204195 static void ish_remove(struct pci_dev *pdev)
205196 {
206197 struct ishtp_device *ishtp_dev = pci_get_drvdata(pdev);
207
- struct ish_hw *hw = to_ish_hw(ishtp_dev);
208198
209199 ishtp_bus_remove_all_clients(ishtp_dev, false);
210200 ish_device_disable(ishtp_dev);
211
-
212
- free_irq(pdev->irq, ishtp_dev);
213
- pci_iounmap(pdev, hw->mem_addr);
214
- pci_release_regions(pdev);
215
- pci_clear_master(pdev);
216
- pci_disable_device(pdev);
217201 }
218202
219203 static struct device __maybe_unused *ish_resume_device;
....@@ -234,17 +218,11 @@
234218 {
235219 struct pci_dev *pdev = to_pci_dev(ish_resume_device);
236220 struct ishtp_device *dev = pci_get_drvdata(pdev);
237
- uint32_t fwsts;
238221 int ret;
239222
240
- /* Get ISH FW status */
241
- fwsts = IPC_GET_ISH_FWSTS(dev->ops->get_fw_status(dev));
223
+ if (ish_should_leave_d0i3(pdev) && !dev->suspend_flag) {
224
+ disable_irq_wake(pdev->irq);
242225
243
- /*
244
- * If currently, in ISH FW, sensor app is loaded or beyond that,
245
- * it means ISH isn't powered off, in this case, send a resume message.
246
- */
247
- if (fwsts >= FWSTS_SENSOR_APP_LOADED) {
248226 ishtp_send_resume(dev);
249227
250228 /* Waiting to get resume response */
....@@ -252,16 +230,20 @@
252230 ret = wait_event_interruptible_timeout(dev->resume_wait,
253231 !dev->resume_flag,
254232 msecs_to_jiffies(WAIT_FOR_RESUME_ACK_MS));
255
- }
256233
257
- /*
258
- * If in ISH FW, sensor app isn't loaded yet, or no resume response.
259
- * That means this platform is not S0ix compatible, or something is
260
- * wrong with ISH FW. So on resume, full reboot of ISH processor will
261
- * happen, so need to go through init sequence again.
262
- */
263
- if (dev->resume_flag)
234
+ /*
235
+ * If the flag is not cleared, something is wrong with ISH FW.
236
+ * So on resume, need to go through init sequence again.
237
+ */
238
+ if (dev->resume_flag)
239
+ ish_init(dev);
240
+ } else {
241
+ /*
242
+ * Resume from the D3, full reboot of ISH processor will happen,
243
+ * so need to go through init sequence again.
244
+ */
264245 ish_init(dev);
246
+ }
265247 }
266248
267249 /**
....@@ -277,23 +259,46 @@
277259 struct pci_dev *pdev = to_pci_dev(device);
278260 struct ishtp_device *dev = pci_get_drvdata(pdev);
279261
280
- enable_irq_wake(pdev->irq);
281
- /*
282
- * If previous suspend hasn't been asnwered then ISH is likely dead,
283
- * don't attempt nested notification
284
- */
285
- if (dev->suspend_flag)
286
- return 0;
262
+ if (ish_should_enter_d0i3(pdev)) {
263
+ /*
264
+ * If previous suspend hasn't been asnwered then ISH is likely
265
+ * dead, don't attempt nested notification
266
+ */
267
+ if (dev->suspend_flag)
268
+ return 0;
287269
288
- dev->resume_flag = 0;
289
- dev->suspend_flag = 1;
290
- ishtp_send_suspend(dev);
270
+ dev->resume_flag = 0;
271
+ dev->suspend_flag = 1;
272
+ ishtp_send_suspend(dev);
291273
292
- /* 25 ms should be enough for live ISH to flush all IPC buf */
293
- if (dev->suspend_flag)
294
- wait_event_interruptible_timeout(dev->suspend_wait,
295
- !dev->suspend_flag,
296
- msecs_to_jiffies(25));
274
+ /* 25 ms should be enough for live ISH to flush all IPC buf */
275
+ if (dev->suspend_flag)
276
+ wait_event_interruptible_timeout(dev->suspend_wait,
277
+ !dev->suspend_flag,
278
+ msecs_to_jiffies(25));
279
+
280
+ if (dev->suspend_flag) {
281
+ /*
282
+ * It looks like FW halt, clear the DMA bit, and put
283
+ * ISH into D3, and FW would reset on resume.
284
+ */
285
+ ish_disable_dma(dev);
286
+ } else {
287
+ /*
288
+ * Save state so PCI core will keep the device at D0,
289
+ * the ISH would enter D0i3
290
+ */
291
+ pci_save_state(pdev);
292
+
293
+ enable_irq_wake(pdev->irq);
294
+ }
295
+ } else {
296
+ /*
297
+ * Clear the DMA bit before putting ISH into D3,
298
+ * or ISH FW would reset automatically.
299
+ */
300
+ ish_disable_dma(dev);
301
+ }
297302
298303 return 0;
299304 }
....@@ -315,7 +320,6 @@
315320 ish_resume_device = device;
316321 dev->resume_flag = 1;
317322
318
- disable_irq_wake(pdev->irq);
319323 schedule_work(&resume_work);
320324
321325 return 0;