IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> pci_enable_device_mem -> 正文阅读

[系统运维]pci_enable_device_mem

/**
?* pci_enable_device_mem - Initialize a device for use with Memory space
?* @dev: PCI device to be initialized
?*
?*? Initialize device before it's used by a driver. Ask low-level code
?*? to enable Memory resources. Wake up the device if it was suspended.
?*? Beware, this function can fail.
?*/
int pci_enable_device_mem(struct pci_dev *dev)
{
?? ?return pci_enable_device_flags(dev, IORESOURCE_MEM);
}

static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
{
?? ?struct pci_dev *bridge;
?? ?int err;
?? ?int i, bars = 0;

?? ?/*
?? ? * Power state could be unknown at this point, either due to a fresh
?? ? * boot or a device removal call.? So get the current power state
?? ? * so that things like MSI message writing will behave as expected
?? ? * (e.g. if the device really is in D0 at enable time).
?? ? */
?? ?if (dev->pm_cap) {
?? ??? ?u16 pmcsr;
?? ??? ?pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
?? ??? ?dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
?? ?}

?? ?if (atomic_inc_return(&dev->enable_cnt) > 1)
?? ??? ?return 0;?? ??? ?/* already enabled */

?? ?bridge = pci_upstream_bridge(dev);
?? ?if (bridge)
?? ??? ?pci_enable_bridge(bridge);

?? ?/* only skip sriov related */
?? ?for (i = 0; i <= PCI_ROM_RESOURCE; i++)
?? ??? ?if (dev->resource[i].flags & flags)
?? ??? ??? ?bars |= (1 << i);
?? ?for (i = PCI_BRIDGE_RESOURCES; i < DEVICE_COUNT_RESOURCE; i++)
?? ??? ?if (dev->resource[i].flags & flags)
?? ??? ??? ?bars |= (1 << i);

?? ?err = do_pci_enable_device(dev, bars);
?? ?if (err < 0)
?? ??? ?atomic_dec(&dev->enable_cnt);
?? ?return err;
}

static int do_pci_enable_device(struct pci_dev *dev, int bars)
{
?? ?int err;
?? ?struct pci_dev *bridge;
?? ?u16 cmd;
?? ?u8 pin;

?? ?err = pci_set_power_state(dev, PCI_D0);
?? ?if (err < 0 && err != -EIO)
?? ??? ?return err;

?? ?bridge = pci_upstream_bridge(dev);
?? ?if (bridge)
?? ??? ?pcie_aspm_powersave_config_link(bridge);

?? ?err = pcibios_enable_device(dev, bars);
?? ?if (err < 0)
?? ??? ?return err;
?? ?pci_fixup_device(pci_fixup_enable, dev);

?? ?if (dev->msi_enabled || dev->msix_enabled)
?? ??? ?return 0;

?? ?pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
?? ?if (pin) {
?? ??? ?pci_read_config_word(dev, PCI_COMMAND, &cmd);
?? ??? ?if (cmd & PCI_COMMAND_INTX_DISABLE)
?? ??? ??? ?pci_write_config_word(dev, PCI_COMMAND,
?? ??? ??? ??? ??? ?????? cmd & ~PCI_COMMAND_INTX_DISABLE);
?? ?}

?? ?return 0;
}

int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
{
?? ?int error;

?? ?/* bound the state we're entering */
?? ?if (state > PCI_D3cold)
?? ??? ?state = PCI_D3cold;
?? ?else if (state < PCI_D0)
?? ??? ?state = PCI_D0;
?? ?else if ((state == PCI_D1 || state == PCI_D2) && pci_no_d1d2(dev))
?? ??? ?/*
?? ??? ? * If the device or the parent bridge do not support PCI PM,
?? ??? ? * ignore the request if we're doing anything other than putting
?? ??? ? * it into D0 (which would only happen on boot).
?? ??? ? */
?? ??? ?return 0;

?? ?/* Check if we're already there */
?? ?if (dev->current_state == state)
?? ??? ?return 0;

?? ?__pci_start_power_transition(dev, state);

?? ?/* This device is quirked not to be put into D3, so
?? ??? don't put it in D3 */
?? ?if (state >= PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3))
?? ??? ?return 0;

?? ?/*
?? ? * To put device in D3cold, we put device into D3hot in native
?? ? * way, then put device into D3cold with platform ops
?? ? */
?? ?error = pci_raw_set_power_state(dev, state > PCI_D3hot ?
?? ??? ??? ??? ??? ?PCI_D3hot : state);

?? ?if (!__pci_complete_power_transition(dev, state))
?? ??? ?error = 0;

?? ?return error;
}

static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state)
{
?? ?u16 pmcsr;
?? ?bool need_restore = false;

?? ?/* Check if we're already there */
?? ?if (dev->current_state == state)
?? ??? ?return 0;

?? ?if (!dev->pm_cap)
?? ??? ?return -EIO;

?? ?if (state < PCI_D0 || state > PCI_D3hot)
?? ??? ?return -EINVAL;

?? ?/* Validate current state:
?? ? * Can enter D0 from any state, but if we can only go deeper
?? ? * to sleep if we're already in a low power state
?? ? */
?? ?if (state != PCI_D0 && dev->current_state <= PCI_D3cold
?? ???? && dev->current_state > state) {
?? ??? ?dev_err(&dev->dev, "invalid power transition (from state %d to %d)\n",
?? ??? ??? ?dev->current_state, state);
?? ??? ?return -EINVAL;
?? ?}

?? ?/* check if this device supports the desired state */
?? ?if ((state == PCI_D1 && !dev->d1_support)
?? ??? || (state == PCI_D2 && !dev->d2_support))
?? ??? ?return -EIO;

?? ?pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);

?? ?/* If we're (effectively) in D3, force entire word to 0.
?? ? * This doesn't affect PME_Status, disables PME_En, and
?? ? * sets PowerState to 0.
?? ? */
?? ?switch (dev->current_state) {
?? ?case PCI_D0:
?? ?case PCI_D1:
?? ?case PCI_D2:
?? ??? ?pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
?? ??? ?pmcsr |= state;
?? ??? ?break;
?? ?case PCI_D3hot:
?? ?case PCI_D3cold:
?? ?case PCI_UNKNOWN: /* Boot-up */
?? ??? ?if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot
?? ??? ? && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET))
?? ??? ??? ?need_restore = true;
?? ??? ?/* Fall-through: force to D0 */
?? ?default:
?? ??? ?pmcsr = 0;
?? ??? ?break;
?? ?}

?? ?/* enter specified state */
?? ?pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr);

?? ?/* Mandatory power management transition delays */
?? ?/* see PCI PM 1.1 5.6.1 table 18 */
?? ?if (state == PCI_D3hot || dev->current_state == PCI_D3hot)
?? ??? ?pci_dev_d3_sleep(dev);
?? ?else if (state == PCI_D2 || dev->current_state == PCI_D2)
?? ??? ?udelay(PCI_PM_D2_DELAY);

?? ?pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
?? ?dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
?? ?if (dev->current_state != state && printk_ratelimit())
?? ??? ?dev_info(&dev->dev, "Refused to change power state, currently in D%d\n",
?? ??? ??? ? dev->current_state);

?? ?/*
?? ? * According to section 5.4.1 of the "PCI BUS POWER MANAGEMENT
?? ? * INTERFACE SPECIFICATION, REV. 1.2", a device transitioning
?? ? * from D3hot to D0 _may_ perform an internal reset, thereby
?? ? * going to "D0 Uninitialized" rather than "D0 Initialized".
?? ? * For example, at least some versions of the 3c905B and the
?? ? * 3c556B exhibit this behaviour.
?? ? *
?? ? * At least some laptop BIOSen (e.g. the Thinkpad T21) leave
?? ? * devices in a D3hot state at boot.? Consequently, we need to
?? ? * restore at least the BARs so that the device will be
?? ? * accessible to its driver.
?? ? */
?? ?if (need_restore)
?? ??? ?pci_restore_bars(dev);

?? ?if (dev->bus->self)
?? ??? ?pcie_aspm_pm_state_change(dev->bus->self);

?? ?return 0;
}

/**
?* pci_restore_bars - restore a device's BAR values (e.g. after wake-up)
?* @dev: PCI device to have its BARs restored
?*
?* Restore the BAR values for a given device, so as to make it
?* accessible by its driver.
?*/
static void pci_restore_bars(struct pci_dev *dev)
{
?? ?int i;

?? ?for (i = 0; i < PCI_BRIDGE_RESOURCES; i++)
?? ??? ?pci_update_resource(dev, i);
}

void pci_update_resource(struct pci_dev *dev, int resno)
{
?? ?if (resno <= PCI_ROM_RESOURCE)
?? ??? ?pci_std_update_resource(dev, resno);
#ifdef CONFIG_PCI_IOV
?? ?else if (resno >= PCI_IOV_RESOURCES && resno <= PCI_IOV_RESOURCE_END)
?? ??? ?pci_iov_update_resource(dev, resno);
#endif
}

static void pci_std_update_resource(struct pci_dev *dev, int resno)
{
?? ?struct pci_bus_region region;
?? ?bool disable;
?? ?u16 cmd;
?? ?u32 new, check, mask;
?? ?int reg;
?? ?struct resource *res = dev->resource + resno;

?? ?/* Per SR-IOV spec 3.4.1.11, VF BARs are RO zero */
?? ?if (dev->is_virtfn)
?? ??? ?return;

?? ?/*
?? ? * Ignore resources for unimplemented BARs and unused resource slots
?? ? * for 64 bit BARs.
?? ? */
?? ?if (!res->flags)
?? ??? ?return;

?? ?if (res->flags & IORESOURCE_UNSET)
?? ??? ?return;

?? ?/*
?? ? * Ignore non-moveable resources.? This might be legacy resources for
?? ? * which no functional BAR register exists or another important
?? ? * system resource we shouldn't move around.
?? ? */
?? ?if (res->flags & IORESOURCE_PCI_FIXED)
?? ??? ?return;

?? ?pcibios_resource_to_bus(dev->bus, &region, res);
?? ?new = region.start;

?? ?if (res->flags & IORESOURCE_IO) {
?? ??? ?mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
?? ??? ?new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK;
?? ?} else if (resno == PCI_ROM_RESOURCE) {
?? ??? ?mask = PCI_ROM_ADDRESS_MASK;
?? ?} else {
?? ??? ?mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
?? ??? ?new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
?? ?}

?? ?if (resno < PCI_ROM_RESOURCE) {
?? ??? ?reg = PCI_BASE_ADDRESS_0 + 4 * resno;
?? ?} else if (resno == PCI_ROM_RESOURCE) {

?? ??? ?/*
?? ??? ? * Apparently some Matrox devices have ROM BARs that read
?? ??? ? * as zero when disabled, so don't update ROM BARs unless
?? ??? ? * they're enabled.? See https://lkml.org/lkml/2005/8/30/138.
?? ??? ? */
?? ??? ?if (!(res->flags & IORESOURCE_ROM_ENABLE))
?? ??? ??? ?return;

?? ??? ?reg = dev->rom_base_reg;
?? ??? ?new |= PCI_ROM_ADDRESS_ENABLE;
?? ?} else
?? ??? ?return;

?? ?/*
?? ? * We can't update a 64-bit BAR atomically, so when possible,
?? ? * disable decoding so that a half-updated BAR won't conflict
?? ? * with another device.
?? ? */
?? ?disable = (res->flags & IORESOURCE_MEM_64) && !dev->mmio_always_on;
?? ?if (disable) {
?? ??? ?pci_read_config_word(dev, PCI_COMMAND, &cmd);
?? ??? ?pci_write_config_word(dev, PCI_COMMAND,
?? ??? ??? ??? ?????? cmd & ~PCI_COMMAND_MEMORY);
?? ?}

?? ?pci_write_config_dword(dev, reg, new);
?? ?pci_read_config_dword(dev, reg, &check);

?? ?if ((new ^ check) & mask) {
?? ??? ?dev_err(&dev->dev, "BAR %d: error updating (%#08x != %#08x)\n",
?? ??? ??? ?resno, new, check);
?? ?}

?? ?if (res->flags & IORESOURCE_MEM_64) {
?? ??? ?new = region.start >> 16 >> 16;
?? ??? ?pci_write_config_dword(dev, reg + 4, new);
?? ??? ?pci_read_config_dword(dev, reg + 4, &check);
?? ??? ?if (check != new) {
?? ??? ??? ?dev_err(&dev->dev, "BAR %d: error updating (high %#08x != %#08x)\n",
?? ??? ??? ??? ?resno, new, check);
?? ??? ?}
?? ?}

?? ?if (disable)
?? ??? ?pci_write_config_word(dev, PCI_COMMAND, cmd);
}

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:57:31  更:2022-04-09 19:01:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 22:29:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码