.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * IOSF-SB MailBox Interface Driver |
---|
3 | 4 | * Copyright (c) 2013, Intel Corporation. |
---|
4 | 5 | * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms and conditions of the GNU General Public License, |
---|
7 | | - * version 2, as published by the Free Software Foundation. |
---|
8 | | - * |
---|
9 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
---|
10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
---|
11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
---|
12 | | - * more details. |
---|
13 | | - * |
---|
14 | | - * |
---|
15 | 6 | * The IOSF-SB is a fabric bus available on Atom based SOC's that uses a |
---|
16 | | - * mailbox interface (MBI) to communicate with mutiple devices. This |
---|
| 7 | + * mailbox interface (MBI) to communicate with multiple devices. This |
---|
17 | 8 | * driver implements access to this interface for those platforms that can |
---|
18 | 9 | * enumerate the device using PCI. |
---|
19 | 10 | */ |
---|
20 | 11 | |
---|
| 12 | +#include <linux/delay.h> |
---|
21 | 13 | #include <linux/module.h> |
---|
22 | 14 | #include <linux/init.h> |
---|
23 | 15 | #include <linux/spinlock.h> |
---|
24 | 16 | #include <linux/pci.h> |
---|
25 | 17 | #include <linux/debugfs.h> |
---|
26 | 18 | #include <linux/capability.h> |
---|
| 19 | +#include <linux/pm_qos.h> |
---|
| 20 | +#include <linux/wait.h> |
---|
27 | 21 | |
---|
28 | 22 | #include <asm/iosf_mbi.h> |
---|
29 | 23 | |
---|
30 | | -#define PCI_DEVICE_ID_BAYTRAIL 0x0F00 |
---|
31 | | -#define PCI_DEVICE_ID_BRASWELL 0x2280 |
---|
32 | | -#define PCI_DEVICE_ID_QUARK_X1000 0x0958 |
---|
33 | | -#define PCI_DEVICE_ID_TANGIER 0x1170 |
---|
| 24 | +#define PCI_DEVICE_ID_INTEL_BAYTRAIL 0x0F00 |
---|
| 25 | +#define PCI_DEVICE_ID_INTEL_BRASWELL 0x2280 |
---|
| 26 | +#define PCI_DEVICE_ID_INTEL_QUARK_X1000 0x0958 |
---|
| 27 | +#define PCI_DEVICE_ID_INTEL_TANGIER 0x1170 |
---|
34 | 28 | |
---|
35 | 29 | static struct pci_dev *mbi_pdev; |
---|
36 | 30 | static DEFINE_SPINLOCK(iosf_mbi_lock); |
---|
37 | | -static DEFINE_MUTEX(iosf_mbi_punit_mutex); |
---|
38 | | -static BLOCKING_NOTIFIER_HEAD(iosf_mbi_pmic_bus_access_notifier); |
---|
| 31 | + |
---|
| 32 | +/**************** Generic iosf_mbi access helpers ****************/ |
---|
39 | 33 | |
---|
40 | 34 | static inline u32 iosf_mbi_form_mcr(u8 op, u8 port, u8 offset) |
---|
41 | 35 | { |
---|
.. | .. |
---|
192 | 186 | } |
---|
193 | 187 | EXPORT_SYMBOL(iosf_mbi_available); |
---|
194 | 188 | |
---|
| 189 | +/* |
---|
| 190 | + **************** P-Unit/kernel shared I2C bus arbritration **************** |
---|
| 191 | + * |
---|
| 192 | + * Some Bay Trail and Cherry Trail devices have the P-Unit and us (the kernel) |
---|
| 193 | + * share a single I2C bus to the PMIC. Below are helpers to arbitrate the |
---|
| 194 | + * accesses between the kernel and the P-Unit. |
---|
| 195 | + * |
---|
| 196 | + * See arch/x86/include/asm/iosf_mbi.h for kernel-doc text for each function. |
---|
| 197 | + */ |
---|
| 198 | + |
---|
| 199 | +#define SEMAPHORE_TIMEOUT 500 |
---|
| 200 | +#define PUNIT_SEMAPHORE_BYT 0x7 |
---|
| 201 | +#define PUNIT_SEMAPHORE_CHT 0x10e |
---|
| 202 | +#define PUNIT_SEMAPHORE_BIT BIT(0) |
---|
| 203 | +#define PUNIT_SEMAPHORE_ACQUIRE BIT(1) |
---|
| 204 | + |
---|
| 205 | +static DEFINE_MUTEX(iosf_mbi_pmic_access_mutex); |
---|
| 206 | +static BLOCKING_NOTIFIER_HEAD(iosf_mbi_pmic_bus_access_notifier); |
---|
| 207 | +static DECLARE_WAIT_QUEUE_HEAD(iosf_mbi_pmic_access_waitq); |
---|
| 208 | +static u32 iosf_mbi_pmic_punit_access_count; |
---|
| 209 | +static u32 iosf_mbi_pmic_i2c_access_count; |
---|
| 210 | +static u32 iosf_mbi_sem_address; |
---|
| 211 | +static unsigned long iosf_mbi_sem_acquired; |
---|
| 212 | +static struct pm_qos_request iosf_mbi_pm_qos; |
---|
| 213 | + |
---|
195 | 214 | void iosf_mbi_punit_acquire(void) |
---|
196 | 215 | { |
---|
197 | | - mutex_lock(&iosf_mbi_punit_mutex); |
---|
| 216 | + /* Wait for any I2C PMIC accesses from in kernel drivers to finish. */ |
---|
| 217 | + mutex_lock(&iosf_mbi_pmic_access_mutex); |
---|
| 218 | + while (iosf_mbi_pmic_i2c_access_count != 0) { |
---|
| 219 | + mutex_unlock(&iosf_mbi_pmic_access_mutex); |
---|
| 220 | + wait_event(iosf_mbi_pmic_access_waitq, |
---|
| 221 | + iosf_mbi_pmic_i2c_access_count == 0); |
---|
| 222 | + mutex_lock(&iosf_mbi_pmic_access_mutex); |
---|
| 223 | + } |
---|
| 224 | + /* |
---|
| 225 | + * We do not need to do anything to allow the PUNIT to safely access |
---|
| 226 | + * the PMIC, other then block in kernel accesses to the PMIC. |
---|
| 227 | + */ |
---|
| 228 | + iosf_mbi_pmic_punit_access_count++; |
---|
| 229 | + mutex_unlock(&iosf_mbi_pmic_access_mutex); |
---|
198 | 230 | } |
---|
199 | 231 | EXPORT_SYMBOL(iosf_mbi_punit_acquire); |
---|
200 | 232 | |
---|
201 | 233 | void iosf_mbi_punit_release(void) |
---|
202 | 234 | { |
---|
203 | | - mutex_unlock(&iosf_mbi_punit_mutex); |
---|
| 235 | + bool do_wakeup; |
---|
| 236 | + |
---|
| 237 | + mutex_lock(&iosf_mbi_pmic_access_mutex); |
---|
| 238 | + iosf_mbi_pmic_punit_access_count--; |
---|
| 239 | + do_wakeup = iosf_mbi_pmic_punit_access_count == 0; |
---|
| 240 | + mutex_unlock(&iosf_mbi_pmic_access_mutex); |
---|
| 241 | + |
---|
| 242 | + if (do_wakeup) |
---|
| 243 | + wake_up(&iosf_mbi_pmic_access_waitq); |
---|
204 | 244 | } |
---|
205 | 245 | EXPORT_SYMBOL(iosf_mbi_punit_release); |
---|
| 246 | + |
---|
| 247 | +static int iosf_mbi_get_sem(u32 *sem) |
---|
| 248 | +{ |
---|
| 249 | + int ret; |
---|
| 250 | + |
---|
| 251 | + ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, |
---|
| 252 | + iosf_mbi_sem_address, sem); |
---|
| 253 | + if (ret) { |
---|
| 254 | + dev_err(&mbi_pdev->dev, "Error P-Unit semaphore read failed\n"); |
---|
| 255 | + return ret; |
---|
| 256 | + } |
---|
| 257 | + |
---|
| 258 | + *sem &= PUNIT_SEMAPHORE_BIT; |
---|
| 259 | + return 0; |
---|
| 260 | +} |
---|
| 261 | + |
---|
| 262 | +static void iosf_mbi_reset_semaphore(void) |
---|
| 263 | +{ |
---|
| 264 | + if (iosf_mbi_modify(BT_MBI_UNIT_PMC, MBI_REG_READ, |
---|
| 265 | + iosf_mbi_sem_address, 0, PUNIT_SEMAPHORE_BIT)) |
---|
| 266 | + dev_err(&mbi_pdev->dev, "Error P-Unit semaphore reset failed\n"); |
---|
| 267 | + |
---|
| 268 | + cpu_latency_qos_update_request(&iosf_mbi_pm_qos, PM_QOS_DEFAULT_VALUE); |
---|
| 269 | + |
---|
| 270 | + blocking_notifier_call_chain(&iosf_mbi_pmic_bus_access_notifier, |
---|
| 271 | + MBI_PMIC_BUS_ACCESS_END, NULL); |
---|
| 272 | +} |
---|
| 273 | + |
---|
| 274 | +/* |
---|
| 275 | + * This function blocks P-Unit accesses to the PMIC I2C bus, so that kernel |
---|
| 276 | + * I2C code, such as e.g. a fuel-gauge driver, can access it safely. |
---|
| 277 | + * |
---|
| 278 | + * This function may be called by I2C controller code while an I2C driver has |
---|
| 279 | + * already blocked P-Unit accesses because it wants them blocked over multiple |
---|
| 280 | + * i2c-transfers, for e.g. read-modify-write of an I2C client register. |
---|
| 281 | + * |
---|
| 282 | + * To allow safe PMIC i2c bus accesses this function takes the following steps: |
---|
| 283 | + * |
---|
| 284 | + * 1) Some code sends request to the P-Unit which make it access the PMIC |
---|
| 285 | + * I2C bus. Testing has shown that the P-Unit does not check its internal |
---|
| 286 | + * PMIC bus semaphore for these requests. Callers of these requests call |
---|
| 287 | + * iosf_mbi_punit_acquire()/_release() around their P-Unit accesses, these |
---|
| 288 | + * functions increase/decrease iosf_mbi_pmic_punit_access_count, so first |
---|
| 289 | + * we wait for iosf_mbi_pmic_punit_access_count to become 0. |
---|
| 290 | + * |
---|
| 291 | + * 2) Check iosf_mbi_pmic_i2c_access_count, if access has already |
---|
| 292 | + * been blocked by another caller, we only need to increment |
---|
| 293 | + * iosf_mbi_pmic_i2c_access_count and we can skip the other steps. |
---|
| 294 | + * |
---|
| 295 | + * 3) Some code makes such P-Unit requests from atomic contexts where it |
---|
| 296 | + * cannot call iosf_mbi_punit_acquire() as that may sleep. |
---|
| 297 | + * As the second step we call a notifier chain which allows any code |
---|
| 298 | + * needing P-Unit resources from atomic context to acquire them before |
---|
| 299 | + * we take control over the PMIC I2C bus. |
---|
| 300 | + * |
---|
| 301 | + * 4) When CPU cores enter C6 or C7 the P-Unit needs to talk to the PMIC |
---|
| 302 | + * if this happens while the kernel itself is accessing the PMIC I2C bus |
---|
| 303 | + * the SoC hangs. |
---|
| 304 | + * As the third step we call cpu_latency_qos_update_request() to disallow the |
---|
| 305 | + * CPU to enter C6 or C7. |
---|
| 306 | + * |
---|
| 307 | + * 5) The P-Unit has a PMIC bus semaphore which we can request to stop |
---|
| 308 | + * autonomous P-Unit tasks from accessing the PMIC I2C bus while we hold it. |
---|
| 309 | + * As the fourth and final step we request this semaphore and wait for our |
---|
| 310 | + * request to be acknowledged. |
---|
| 311 | + */ |
---|
| 312 | +int iosf_mbi_block_punit_i2c_access(void) |
---|
| 313 | +{ |
---|
| 314 | + unsigned long start, end; |
---|
| 315 | + int ret = 0; |
---|
| 316 | + u32 sem; |
---|
| 317 | + |
---|
| 318 | + if (WARN_ON(!mbi_pdev || !iosf_mbi_sem_address)) |
---|
| 319 | + return -ENXIO; |
---|
| 320 | + |
---|
| 321 | + mutex_lock(&iosf_mbi_pmic_access_mutex); |
---|
| 322 | + |
---|
| 323 | + while (iosf_mbi_pmic_punit_access_count != 0) { |
---|
| 324 | + mutex_unlock(&iosf_mbi_pmic_access_mutex); |
---|
| 325 | + wait_event(iosf_mbi_pmic_access_waitq, |
---|
| 326 | + iosf_mbi_pmic_punit_access_count == 0); |
---|
| 327 | + mutex_lock(&iosf_mbi_pmic_access_mutex); |
---|
| 328 | + } |
---|
| 329 | + |
---|
| 330 | + if (iosf_mbi_pmic_i2c_access_count > 0) |
---|
| 331 | + goto success; |
---|
| 332 | + |
---|
| 333 | + blocking_notifier_call_chain(&iosf_mbi_pmic_bus_access_notifier, |
---|
| 334 | + MBI_PMIC_BUS_ACCESS_BEGIN, NULL); |
---|
| 335 | + |
---|
| 336 | + /* |
---|
| 337 | + * Disallow the CPU to enter C6 or C7 state, entering these states |
---|
| 338 | + * requires the P-Unit to talk to the PMIC and if this happens while |
---|
| 339 | + * we're holding the semaphore, the SoC hangs. |
---|
| 340 | + */ |
---|
| 341 | + cpu_latency_qos_update_request(&iosf_mbi_pm_qos, 0); |
---|
| 342 | + |
---|
| 343 | + /* host driver writes to side band semaphore register */ |
---|
| 344 | + ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, |
---|
| 345 | + iosf_mbi_sem_address, PUNIT_SEMAPHORE_ACQUIRE); |
---|
| 346 | + if (ret) { |
---|
| 347 | + dev_err(&mbi_pdev->dev, "Error P-Unit semaphore request failed\n"); |
---|
| 348 | + goto error; |
---|
| 349 | + } |
---|
| 350 | + |
---|
| 351 | + /* host driver waits for bit 0 to be set in semaphore register */ |
---|
| 352 | + start = jiffies; |
---|
| 353 | + end = start + msecs_to_jiffies(SEMAPHORE_TIMEOUT); |
---|
| 354 | + do { |
---|
| 355 | + ret = iosf_mbi_get_sem(&sem); |
---|
| 356 | + if (!ret && sem) { |
---|
| 357 | + iosf_mbi_sem_acquired = jiffies; |
---|
| 358 | + dev_dbg(&mbi_pdev->dev, "P-Unit semaphore acquired after %ums\n", |
---|
| 359 | + jiffies_to_msecs(jiffies - start)); |
---|
| 360 | + goto success; |
---|
| 361 | + } |
---|
| 362 | + |
---|
| 363 | + usleep_range(1000, 2000); |
---|
| 364 | + } while (time_before(jiffies, end)); |
---|
| 365 | + |
---|
| 366 | + ret = -ETIMEDOUT; |
---|
| 367 | + dev_err(&mbi_pdev->dev, "Error P-Unit semaphore timed out, resetting\n"); |
---|
| 368 | +error: |
---|
| 369 | + iosf_mbi_reset_semaphore(); |
---|
| 370 | + if (!iosf_mbi_get_sem(&sem)) |
---|
| 371 | + dev_err(&mbi_pdev->dev, "P-Unit semaphore: %d\n", sem); |
---|
| 372 | +success: |
---|
| 373 | + if (!WARN_ON(ret)) |
---|
| 374 | + iosf_mbi_pmic_i2c_access_count++; |
---|
| 375 | + |
---|
| 376 | + mutex_unlock(&iosf_mbi_pmic_access_mutex); |
---|
| 377 | + |
---|
| 378 | + return ret; |
---|
| 379 | +} |
---|
| 380 | +EXPORT_SYMBOL(iosf_mbi_block_punit_i2c_access); |
---|
| 381 | + |
---|
| 382 | +void iosf_mbi_unblock_punit_i2c_access(void) |
---|
| 383 | +{ |
---|
| 384 | + bool do_wakeup = false; |
---|
| 385 | + |
---|
| 386 | + mutex_lock(&iosf_mbi_pmic_access_mutex); |
---|
| 387 | + iosf_mbi_pmic_i2c_access_count--; |
---|
| 388 | + if (iosf_mbi_pmic_i2c_access_count == 0) { |
---|
| 389 | + iosf_mbi_reset_semaphore(); |
---|
| 390 | + dev_dbg(&mbi_pdev->dev, "punit semaphore held for %ums\n", |
---|
| 391 | + jiffies_to_msecs(jiffies - iosf_mbi_sem_acquired)); |
---|
| 392 | + do_wakeup = true; |
---|
| 393 | + } |
---|
| 394 | + mutex_unlock(&iosf_mbi_pmic_access_mutex); |
---|
| 395 | + |
---|
| 396 | + if (do_wakeup) |
---|
| 397 | + wake_up(&iosf_mbi_pmic_access_waitq); |
---|
| 398 | +} |
---|
| 399 | +EXPORT_SYMBOL(iosf_mbi_unblock_punit_i2c_access); |
---|
206 | 400 | |
---|
207 | 401 | int iosf_mbi_register_pmic_bus_access_notifier(struct notifier_block *nb) |
---|
208 | 402 | { |
---|
209 | 403 | int ret; |
---|
210 | 404 | |
---|
211 | 405 | /* Wait for the bus to go inactive before registering */ |
---|
212 | | - mutex_lock(&iosf_mbi_punit_mutex); |
---|
| 406 | + iosf_mbi_punit_acquire(); |
---|
213 | 407 | ret = blocking_notifier_chain_register( |
---|
214 | 408 | &iosf_mbi_pmic_bus_access_notifier, nb); |
---|
215 | | - mutex_unlock(&iosf_mbi_punit_mutex); |
---|
| 409 | + iosf_mbi_punit_release(); |
---|
216 | 410 | |
---|
217 | 411 | return ret; |
---|
218 | 412 | } |
---|
.. | .. |
---|
233 | 427 | int ret; |
---|
234 | 428 | |
---|
235 | 429 | /* Wait for the bus to go inactive before unregistering */ |
---|
236 | | - mutex_lock(&iosf_mbi_punit_mutex); |
---|
| 430 | + iosf_mbi_punit_acquire(); |
---|
237 | 431 | ret = iosf_mbi_unregister_pmic_bus_access_notifier_unlocked(nb); |
---|
238 | | - mutex_unlock(&iosf_mbi_punit_mutex); |
---|
| 432 | + iosf_mbi_punit_release(); |
---|
239 | 433 | |
---|
240 | 434 | return ret; |
---|
241 | 435 | } |
---|
242 | 436 | EXPORT_SYMBOL(iosf_mbi_unregister_pmic_bus_access_notifier); |
---|
243 | 437 | |
---|
244 | | -int iosf_mbi_call_pmic_bus_access_notifier_chain(unsigned long val, void *v) |
---|
245 | | -{ |
---|
246 | | - return blocking_notifier_call_chain( |
---|
247 | | - &iosf_mbi_pmic_bus_access_notifier, val, v); |
---|
248 | | -} |
---|
249 | | -EXPORT_SYMBOL(iosf_mbi_call_pmic_bus_access_notifier_chain); |
---|
250 | | - |
---|
251 | 438 | void iosf_mbi_assert_punit_acquired(void) |
---|
252 | 439 | { |
---|
253 | | - WARN_ON(!mutex_is_locked(&iosf_mbi_punit_mutex)); |
---|
| 440 | + WARN_ON(iosf_mbi_pmic_punit_access_count == 0); |
---|
254 | 441 | } |
---|
255 | 442 | EXPORT_SYMBOL(iosf_mbi_assert_punit_acquired); |
---|
| 443 | + |
---|
| 444 | +/**************** iosf_mbi debug code ****************/ |
---|
256 | 445 | |
---|
257 | 446 | #ifdef CONFIG_IOSF_MBI_DEBUG |
---|
258 | 447 | static u32 dbg_mdr; |
---|
.. | .. |
---|
296 | 485 | |
---|
297 | 486 | static void iosf_sideband_debug_init(void) |
---|
298 | 487 | { |
---|
299 | | - struct dentry *d; |
---|
300 | | - |
---|
301 | 488 | iosf_dbg = debugfs_create_dir("iosf_sb", NULL); |
---|
302 | | - if (IS_ERR_OR_NULL(iosf_dbg)) |
---|
303 | | - return; |
---|
304 | 489 | |
---|
305 | 490 | /* mdr */ |
---|
306 | | - d = debugfs_create_x32("mdr", 0660, iosf_dbg, &dbg_mdr); |
---|
307 | | - if (!d) |
---|
308 | | - goto cleanup; |
---|
| 491 | + debugfs_create_x32("mdr", 0660, iosf_dbg, &dbg_mdr); |
---|
309 | 492 | |
---|
310 | 493 | /* mcrx */ |
---|
311 | | - d = debugfs_create_x32("mcrx", 0660, iosf_dbg, &dbg_mcrx); |
---|
312 | | - if (!d) |
---|
313 | | - goto cleanup; |
---|
| 494 | + debugfs_create_x32("mcrx", 0660, iosf_dbg, &dbg_mcrx); |
---|
314 | 495 | |
---|
315 | 496 | /* mcr - initiates mailbox tranaction */ |
---|
316 | | - d = debugfs_create_file("mcr", 0660, iosf_dbg, &dbg_mcr, &iosf_mcr_fops); |
---|
317 | | - if (!d) |
---|
318 | | - goto cleanup; |
---|
319 | | - |
---|
320 | | - return; |
---|
321 | | - |
---|
322 | | -cleanup: |
---|
323 | | - debugfs_remove_recursive(d); |
---|
| 497 | + debugfs_create_file("mcr", 0660, iosf_dbg, &dbg_mcr, &iosf_mcr_fops); |
---|
324 | 498 | } |
---|
325 | 499 | |
---|
326 | 500 | static void iosf_debugfs_init(void) |
---|
.. | .. |
---|
338 | 512 | #endif /* CONFIG_IOSF_MBI_DEBUG */ |
---|
339 | 513 | |
---|
340 | 514 | static int iosf_mbi_probe(struct pci_dev *pdev, |
---|
341 | | - const struct pci_device_id *unused) |
---|
| 515 | + const struct pci_device_id *dev_id) |
---|
342 | 516 | { |
---|
343 | 517 | int ret; |
---|
344 | 518 | |
---|
.. | .. |
---|
349 | 523 | } |
---|
350 | 524 | |
---|
351 | 525 | mbi_pdev = pci_dev_get(pdev); |
---|
| 526 | + iosf_mbi_sem_address = dev_id->driver_data; |
---|
| 527 | + |
---|
352 | 528 | return 0; |
---|
353 | 529 | } |
---|
354 | 530 | |
---|
355 | 531 | static const struct pci_device_id iosf_mbi_pci_ids[] = { |
---|
356 | | - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BAYTRAIL) }, |
---|
357 | | - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_BRASWELL) }, |
---|
358 | | - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_QUARK_X1000) }, |
---|
359 | | - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_TANGIER) }, |
---|
| 532 | + { PCI_DEVICE_DATA(INTEL, BAYTRAIL, PUNIT_SEMAPHORE_BYT) }, |
---|
| 533 | + { PCI_DEVICE_DATA(INTEL, BRASWELL, PUNIT_SEMAPHORE_CHT) }, |
---|
| 534 | + { PCI_DEVICE_DATA(INTEL, QUARK_X1000, 0) }, |
---|
| 535 | + { PCI_DEVICE_DATA(INTEL, TANGIER, 0) }, |
---|
360 | 536 | { 0, }, |
---|
361 | 537 | }; |
---|
362 | 538 | MODULE_DEVICE_TABLE(pci, iosf_mbi_pci_ids); |
---|
.. | .. |
---|
371 | 547 | { |
---|
372 | 548 | iosf_debugfs_init(); |
---|
373 | 549 | |
---|
| 550 | + cpu_latency_qos_add_request(&iosf_mbi_pm_qos, PM_QOS_DEFAULT_VALUE); |
---|
| 551 | + |
---|
374 | 552 | return pci_register_driver(&iosf_mbi_pci_driver); |
---|
375 | 553 | } |
---|
376 | 554 | |
---|
.. | .. |
---|
381 | 559 | pci_unregister_driver(&iosf_mbi_pci_driver); |
---|
382 | 560 | pci_dev_put(mbi_pdev); |
---|
383 | 561 | mbi_pdev = NULL; |
---|
| 562 | + |
---|
| 563 | + cpu_latency_qos_remove_request(&iosf_mbi_pm_qos); |
---|
384 | 564 | } |
---|
385 | 565 | |
---|
386 | 566 | module_init(iosf_mbi_init); |
---|