mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 12:16:20 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: (21 commits) pciehp: fix error message about getting hotplug control pci/irq: let pci_device_shutdown to call pci_msi_shutdown v2 pci/irq: restore mask_bits in msi shutdown -v3 doc: replace yet another dev with pdev for consistency in DMA-mapping.txt PCI: don't expose struct pci_vpd to userspace doc: fix an incorrect suggestion to pass NULL for PCI like buses Consistently use pdev as the variable of type struct pci_dev *. pciehp: Fix command write shpchp: fix slot name make pciehp_acpi_get_hp_hw_control_from_firmware() pciehp: Clean up pcie_init() pciehp: Mask hotplug interrupt at controller release pciehp: Remove useless hotplug interrupt enabling pciehp: Fix wrong slot capability check pciehp: Fix wrong slot control register access pciehp: Add missing memory barrier pciehp: Fix interrupt event handlig pciehp: fix slot name Update MAINTAINERS with location of PCI tree PCI: Add Intel SCH PCI IDs ...
This commit is contained in:
commit
a217656cb2
13 changed files with 306 additions and 472 deletions
|
@ -315,11 +315,11 @@ you should do:
|
||||||
|
|
||||||
dma_addr_t dma_handle;
|
dma_addr_t dma_handle;
|
||||||
|
|
||||||
cpu_addr = pci_alloc_consistent(dev, size, &dma_handle);
|
cpu_addr = pci_alloc_consistent(pdev, size, &dma_handle);
|
||||||
|
|
||||||
where dev is a struct pci_dev *. You should pass NULL for PCI like buses
|
where pdev is a struct pci_dev *. This may be called in interrupt context.
|
||||||
where devices don't have struct pci_dev (like ISA, EISA). This may be
|
You should use dma_alloc_coherent (see DMA-API.txt) for buses
|
||||||
called in interrupt context.
|
where devices don't have struct pci_dev (like ISA, EISA).
|
||||||
|
|
||||||
This argument is needed because the DMA translations may be bus
|
This argument is needed because the DMA translations may be bus
|
||||||
specific (and often is private to the bus which the device is attached
|
specific (and often is private to the bus which the device is attached
|
||||||
|
@ -332,7 +332,7 @@ __get_free_pages (but takes size instead of a page order). If your
|
||||||
driver needs regions sized smaller than a page, you may prefer using
|
driver needs regions sized smaller than a page, you may prefer using
|
||||||
the pci_pool interface, described below.
|
the pci_pool interface, described below.
|
||||||
|
|
||||||
The consistent DMA mapping interfaces, for non-NULL dev, will by
|
The consistent DMA mapping interfaces, for non-NULL pdev, will by
|
||||||
default return a DMA address which is SAC (Single Address Cycle)
|
default return a DMA address which is SAC (Single Address Cycle)
|
||||||
addressable. Even if the device indicates (via PCI dma mask) that it
|
addressable. Even if the device indicates (via PCI dma mask) that it
|
||||||
may address the upper 32-bits and thus perform DAC cycles, consistent
|
may address the upper 32-bits and thus perform DAC cycles, consistent
|
||||||
|
@ -354,9 +354,9 @@ buffer you receive will not cross a 64K boundary.
|
||||||
|
|
||||||
To unmap and free such a DMA region, you call:
|
To unmap and free such a DMA region, you call:
|
||||||
|
|
||||||
pci_free_consistent(dev, size, cpu_addr, dma_handle);
|
pci_free_consistent(pdev, size, cpu_addr, dma_handle);
|
||||||
|
|
||||||
where dev, size are the same as in the above call and cpu_addr and
|
where pdev, size are the same as in the above call and cpu_addr and
|
||||||
dma_handle are the values pci_alloc_consistent returned to you.
|
dma_handle are the values pci_alloc_consistent returned to you.
|
||||||
This function may not be called in interrupt context.
|
This function may not be called in interrupt context.
|
||||||
|
|
||||||
|
@ -371,9 +371,9 @@ Create a pci_pool like this:
|
||||||
|
|
||||||
struct pci_pool *pool;
|
struct pci_pool *pool;
|
||||||
|
|
||||||
pool = pci_pool_create(name, dev, size, align, alloc);
|
pool = pci_pool_create(name, pdev, size, align, alloc);
|
||||||
|
|
||||||
The "name" is for diagnostics (like a kmem_cache name); dev and size
|
The "name" is for diagnostics (like a kmem_cache name); pdev and size
|
||||||
are as above. The device's hardware alignment requirement for this
|
are as above. The device's hardware alignment requirement for this
|
||||||
type of data is "align" (which is expressed in bytes, and must be a
|
type of data is "align" (which is expressed in bytes, and must be a
|
||||||
power of two). If your device has no boundary crossing restrictions,
|
power of two). If your device has no boundary crossing restrictions,
|
||||||
|
@ -472,11 +472,11 @@ To map a single region, you do:
|
||||||
void *addr = buffer->ptr;
|
void *addr = buffer->ptr;
|
||||||
size_t size = buffer->len;
|
size_t size = buffer->len;
|
||||||
|
|
||||||
dma_handle = pci_map_single(dev, addr, size, direction);
|
dma_handle = pci_map_single(pdev, addr, size, direction);
|
||||||
|
|
||||||
and to unmap it:
|
and to unmap it:
|
||||||
|
|
||||||
pci_unmap_single(dev, dma_handle, size, direction);
|
pci_unmap_single(pdev, dma_handle, size, direction);
|
||||||
|
|
||||||
You should call pci_unmap_single when the DMA activity is finished, e.g.
|
You should call pci_unmap_single when the DMA activity is finished, e.g.
|
||||||
from the interrupt which told you that the DMA transfer is done.
|
from the interrupt which told you that the DMA transfer is done.
|
||||||
|
@ -493,17 +493,17 @@ Specifically:
|
||||||
unsigned long offset = buffer->offset;
|
unsigned long offset = buffer->offset;
|
||||||
size_t size = buffer->len;
|
size_t size = buffer->len;
|
||||||
|
|
||||||
dma_handle = pci_map_page(dev, page, offset, size, direction);
|
dma_handle = pci_map_page(pdev, page, offset, size, direction);
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
pci_unmap_page(dev, dma_handle, size, direction);
|
pci_unmap_page(pdev, dma_handle, size, direction);
|
||||||
|
|
||||||
Here, "offset" means byte offset within the given page.
|
Here, "offset" means byte offset within the given page.
|
||||||
|
|
||||||
With scatterlists, you map a region gathered from several regions by:
|
With scatterlists, you map a region gathered from several regions by:
|
||||||
|
|
||||||
int i, count = pci_map_sg(dev, sglist, nents, direction);
|
int i, count = pci_map_sg(pdev, sglist, nents, direction);
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
|
|
||||||
for_each_sg(sglist, sg, count, i) {
|
for_each_sg(sglist, sg, count, i) {
|
||||||
|
@ -527,7 +527,7 @@ accessed sg->address and sg->length as shown above.
|
||||||
|
|
||||||
To unmap a scatterlist, just call:
|
To unmap a scatterlist, just call:
|
||||||
|
|
||||||
pci_unmap_sg(dev, sglist, nents, direction);
|
pci_unmap_sg(pdev, sglist, nents, direction);
|
||||||
|
|
||||||
Again, make sure DMA activity has already finished.
|
Again, make sure DMA activity has already finished.
|
||||||
|
|
||||||
|
@ -550,11 +550,11 @@ correct copy of the DMA buffer.
|
||||||
So, firstly, just map it with pci_map_{single,sg}, and after each DMA
|
So, firstly, just map it with pci_map_{single,sg}, and after each DMA
|
||||||
transfer call either:
|
transfer call either:
|
||||||
|
|
||||||
pci_dma_sync_single_for_cpu(dev, dma_handle, size, direction);
|
pci_dma_sync_single_for_cpu(pdev, dma_handle, size, direction);
|
||||||
|
|
||||||
or:
|
or:
|
||||||
|
|
||||||
pci_dma_sync_sg_for_cpu(dev, sglist, nents, direction);
|
pci_dma_sync_sg_for_cpu(pdev, sglist, nents, direction);
|
||||||
|
|
||||||
as appropriate.
|
as appropriate.
|
||||||
|
|
||||||
|
@ -562,7 +562,7 @@ Then, if you wish to let the device get at the DMA area again,
|
||||||
finish accessing the data with the cpu, and then before actually
|
finish accessing the data with the cpu, and then before actually
|
||||||
giving the buffer to the hardware call either:
|
giving the buffer to the hardware call either:
|
||||||
|
|
||||||
pci_dma_sync_single_for_device(dev, dma_handle, size, direction);
|
pci_dma_sync_single_for_device(pdev, dma_handle, size, direction);
|
||||||
|
|
||||||
or:
|
or:
|
||||||
|
|
||||||
|
@ -739,7 +739,7 @@ failure can be determined by:
|
||||||
|
|
||||||
dma_addr_t dma_handle;
|
dma_addr_t dma_handle;
|
||||||
|
|
||||||
dma_handle = pci_map_single(dev, addr, size, direction);
|
dma_handle = pci_map_single(pdev, addr, size, direction);
|
||||||
if (pci_dma_mapping_error(dma_handle)) {
|
if (pci_dma_mapping_error(dma_handle)) {
|
||||||
/*
|
/*
|
||||||
* reduce current DMA mapping usage,
|
* reduce current DMA mapping usage,
|
||||||
|
|
|
@ -3114,6 +3114,7 @@ P: Jesse Barnes
|
||||||
M: jbarnes@virtuousgeek.org
|
M: jbarnes@virtuousgeek.org
|
||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
L: linux-pci@atrey.karlin.mff.cuni.cz
|
L: linux-pci@atrey.karlin.mff.cuni.cz
|
||||||
|
T: git kernel.org:/pub/scm/linux/kernel/git/jbarnes/pci-2.6.git
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
||||||
PCI HOTPLUG CORE
|
PCI HOTPLUG CORE
|
||||||
|
|
|
@ -93,11 +93,10 @@ struct controller {
|
||||||
u8 slot_device_offset;
|
u8 slot_device_offset;
|
||||||
u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */
|
u32 first_slot; /* First physical slot number */ /* PCIE only has 1 slot */
|
||||||
u8 slot_bus; /* Bus where the slots handled by this controller sit */
|
u8 slot_bus; /* Bus where the slots handled by this controller sit */
|
||||||
u8 ctrlcap;
|
u32 slot_cap;
|
||||||
u8 cap_base;
|
u8 cap_base;
|
||||||
struct timer_list poll_timer;
|
struct timer_list poll_timer;
|
||||||
volatile int cmd_busy;
|
volatile int cmd_busy;
|
||||||
spinlock_t lock;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define INT_BUTTON_IGNORE 0
|
#define INT_BUTTON_IGNORE 0
|
||||||
|
@ -137,13 +136,13 @@ struct controller {
|
||||||
#define HP_SUPR_RM_SUP 0x00000020
|
#define HP_SUPR_RM_SUP 0x00000020
|
||||||
#define EMI_PRSN 0x00020000
|
#define EMI_PRSN 0x00020000
|
||||||
|
|
||||||
#define ATTN_BUTTN(cap) (cap & ATTN_BUTTN_PRSN)
|
#define ATTN_BUTTN(ctrl) ((ctrl)->slot_cap & ATTN_BUTTN_PRSN)
|
||||||
#define POWER_CTRL(cap) (cap & PWR_CTRL_PRSN)
|
#define POWER_CTRL(ctrl) ((ctrl)->slot_cap & PWR_CTRL_PRSN)
|
||||||
#define MRL_SENS(cap) (cap & MRL_SENS_PRSN)
|
#define MRL_SENS(ctrl) ((ctrl)->slot_cap & MRL_SENS_PRSN)
|
||||||
#define ATTN_LED(cap) (cap & ATTN_LED_PRSN)
|
#define ATTN_LED(ctrl) ((ctrl)->slot_cap & ATTN_LED_PRSN)
|
||||||
#define PWR_LED(cap) (cap & PWR_LED_PRSN)
|
#define PWR_LED(ctrl) ((ctrl)->slot_cap & PWR_LED_PRSN)
|
||||||
#define HP_SUPR_RM(cap) (cap & HP_SUPR_RM_SUP)
|
#define HP_SUPR_RM(ctrl) ((ctrl)->slot_cap & HP_SUPR_RM_SUP)
|
||||||
#define EMI(cap) (cap & EMI_PRSN)
|
#define EMI(ctrl) ((ctrl)->slot_cap & EMI_PRSN)
|
||||||
|
|
||||||
extern int pciehp_sysfs_enable_slot(struct slot *slot);
|
extern int pciehp_sysfs_enable_slot(struct slot *slot);
|
||||||
extern int pciehp_sysfs_disable_slot(struct slot *slot);
|
extern int pciehp_sysfs_disable_slot(struct slot *slot);
|
||||||
|
|
|
@ -41,6 +41,7 @@ int pciehp_debug;
|
||||||
int pciehp_poll_mode;
|
int pciehp_poll_mode;
|
||||||
int pciehp_poll_time;
|
int pciehp_poll_time;
|
||||||
int pciehp_force;
|
int pciehp_force;
|
||||||
|
int pciehp_slot_with_bus;
|
||||||
struct workqueue_struct *pciehp_wq;
|
struct workqueue_struct *pciehp_wq;
|
||||||
|
|
||||||
#define DRIVER_VERSION "0.4"
|
#define DRIVER_VERSION "0.4"
|
||||||
|
@ -55,10 +56,12 @@ module_param(pciehp_debug, bool, 0644);
|
||||||
module_param(pciehp_poll_mode, bool, 0644);
|
module_param(pciehp_poll_mode, bool, 0644);
|
||||||
module_param(pciehp_poll_time, int, 0644);
|
module_param(pciehp_poll_time, int, 0644);
|
||||||
module_param(pciehp_force, bool, 0644);
|
module_param(pciehp_force, bool, 0644);
|
||||||
|
module_param(pciehp_slot_with_bus, bool, 0644);
|
||||||
MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
|
MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not");
|
||||||
MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
|
MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not");
|
||||||
MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
|
MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds");
|
||||||
MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
|
MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
|
||||||
|
MODULE_PARM_DESC(pciehp_slot_with_bus, "Use bus number in the slot name");
|
||||||
|
|
||||||
#define PCIE_MODULE_NAME "pciehp"
|
#define PCIE_MODULE_NAME "pciehp"
|
||||||
|
|
||||||
|
@ -193,8 +196,12 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
|
||||||
|
|
||||||
static void make_slot_name(struct slot *slot)
|
static void make_slot_name(struct slot *slot)
|
||||||
{
|
{
|
||||||
|
if (pciehp_slot_with_bus)
|
||||||
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
|
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
|
||||||
slot->bus, slot->number);
|
slot->bus, slot->number);
|
||||||
|
else
|
||||||
|
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
|
||||||
|
slot->number);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_slots(struct controller *ctrl)
|
static int init_slots(struct controller *ctrl)
|
||||||
|
@ -251,7 +258,7 @@ static int init_slots(struct controller *ctrl)
|
||||||
goto error_info;
|
goto error_info;
|
||||||
}
|
}
|
||||||
/* create additional sysfs entries */
|
/* create additional sysfs entries */
|
||||||
if (EMI(ctrl->ctrlcap)) {
|
if (EMI(ctrl)) {
|
||||||
retval = sysfs_create_file(&hotplug_slot->kobj,
|
retval = sysfs_create_file(&hotplug_slot->kobj,
|
||||||
&hotplug_slot_attr_lock.attr);
|
&hotplug_slot_attr_lock.attr);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
@ -284,7 +291,7 @@ static void cleanup_slots(struct controller *ctrl)
|
||||||
list_for_each_safe(tmp, next, &ctrl->slot_list) {
|
list_for_each_safe(tmp, next, &ctrl->slot_list) {
|
||||||
slot = list_entry(tmp, struct slot, slot_list);
|
slot = list_entry(tmp, struct slot, slot_list);
|
||||||
list_del(&slot->slot_list);
|
list_del(&slot->slot_list);
|
||||||
if (EMI(ctrl->ctrlcap))
|
if (EMI(ctrl))
|
||||||
sysfs_remove_file(&slot->hotplug_slot->kobj,
|
sysfs_remove_file(&slot->hotplug_slot->kobj,
|
||||||
&hotplug_slot_attr_lock.attr);
|
&hotplug_slot_attr_lock.attr);
|
||||||
cancel_delayed_work(&slot->work);
|
cancel_delayed_work(&slot->work);
|
||||||
|
@ -305,7 +312,7 @@ static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
|
||||||
|
|
||||||
hotplug_slot->info->attention_status = status;
|
hotplug_slot->info->attention_status = status;
|
||||||
|
|
||||||
if (ATTN_LED(slot->ctrl->ctrlcap))
|
if (ATTN_LED(slot->ctrl))
|
||||||
slot->hpc_ops->set_attention_status(slot, status);
|
slot->hpc_ops->set_attention_status(slot, status);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -472,7 +479,7 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
|
||||||
if (rc) /* -ENODEV: shouldn't happen, but deal with it */
|
if (rc) /* -ENODEV: shouldn't happen, but deal with it */
|
||||||
value = 0;
|
value = 0;
|
||||||
}
|
}
|
||||||
if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
|
if ((POWER_CTRL(ctrl)) && !value) {
|
||||||
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
|
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_out_free_ctrl_slot;
|
goto err_out_free_ctrl_slot;
|
||||||
|
|
|
@ -178,7 +178,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, struct controller *ctrl)
|
||||||
static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
||||||
{
|
{
|
||||||
/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
|
/* turn off slot, turn on Amber LED, turn off Green LED if supported*/
|
||||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
if (POWER_CTRL(ctrl)) {
|
||||||
if (pslot->hpc_ops->power_off_slot(pslot)) {
|
if (pslot->hpc_ops->power_off_slot(pslot)) {
|
||||||
err("%s: Issue of Slot Power Off command failed\n",
|
err("%s: Issue of Slot Power Off command failed\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
@ -186,10 +186,10 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PWR_LED(ctrl->ctrlcap))
|
if (PWR_LED(ctrl))
|
||||||
pslot->hpc_ops->green_led_off(pslot);
|
pslot->hpc_ops->green_led_off(pslot);
|
||||||
|
|
||||||
if (ATTN_LED(ctrl->ctrlcap)) {
|
if (ATTN_LED(ctrl)) {
|
||||||
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
|
if (pslot->hpc_ops->set_attention_status(pslot, 1)) {
|
||||||
err("%s: Issue of Set Attention Led command failed\n",
|
err("%s: Issue of Set Attention Led command failed\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
@ -214,14 +214,14 @@ static int board_added(struct slot *p_slot)
|
||||||
__func__, p_slot->device,
|
__func__, p_slot->device,
|
||||||
ctrl->slot_device_offset, p_slot->hp_slot);
|
ctrl->slot_device_offset, p_slot->hp_slot);
|
||||||
|
|
||||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
if (POWER_CTRL(ctrl)) {
|
||||||
/* Power on slot */
|
/* Power on slot */
|
||||||
retval = p_slot->hpc_ops->power_on_slot(p_slot);
|
retval = p_slot->hpc_ops->power_on_slot(p_slot);
|
||||||
if (retval)
|
if (retval)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PWR_LED(ctrl->ctrlcap))
|
if (PWR_LED(ctrl))
|
||||||
p_slot->hpc_ops->green_led_blink(p_slot);
|
p_slot->hpc_ops->green_led_blink(p_slot);
|
||||||
|
|
||||||
/* Wait for ~1 second */
|
/* Wait for ~1 second */
|
||||||
|
@ -254,7 +254,7 @@ static int board_added(struct slot *p_slot)
|
||||||
*/
|
*/
|
||||||
if (pcie_mch_quirk)
|
if (pcie_mch_quirk)
|
||||||
pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
|
pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
|
||||||
if (PWR_LED(ctrl->ctrlcap))
|
if (PWR_LED(ctrl))
|
||||||
p_slot->hpc_ops->green_led_on(p_slot);
|
p_slot->hpc_ops->green_led_on(p_slot);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -279,7 +279,7 @@ static int remove_board(struct slot *p_slot)
|
||||||
|
|
||||||
dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
|
dbg("In %s, hp_slot = %d\n", __func__, p_slot->hp_slot);
|
||||||
|
|
||||||
if (POWER_CTRL(ctrl->ctrlcap)) {
|
if (POWER_CTRL(ctrl)) {
|
||||||
/* power off slot */
|
/* power off slot */
|
||||||
retval = p_slot->hpc_ops->power_off_slot(p_slot);
|
retval = p_slot->hpc_ops->power_off_slot(p_slot);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
|
@ -289,7 +289,7 @@ static int remove_board(struct slot *p_slot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (PWR_LED(ctrl->ctrlcap))
|
if (PWR_LED(ctrl))
|
||||||
/* turn off Green LED */
|
/* turn off Green LED */
|
||||||
p_slot->hpc_ops->green_led_off(p_slot);
|
p_slot->hpc_ops->green_led_off(p_slot);
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ static void pciehp_power_thread(struct work_struct *work)
|
||||||
case POWERON_STATE:
|
case POWERON_STATE:
|
||||||
mutex_unlock(&p_slot->lock);
|
mutex_unlock(&p_slot->lock);
|
||||||
if (pciehp_enable_slot(p_slot) &&
|
if (pciehp_enable_slot(p_slot) &&
|
||||||
PWR_LED(p_slot->ctrl->ctrlcap))
|
PWR_LED(p_slot->ctrl))
|
||||||
p_slot->hpc_ops->green_led_off(p_slot);
|
p_slot->hpc_ops->green_led_off(p_slot);
|
||||||
mutex_lock(&p_slot->lock);
|
mutex_lock(&p_slot->lock);
|
||||||
p_slot->state = STATIC_STATE;
|
p_slot->state = STATIC_STATE;
|
||||||
|
@ -409,9 +409,9 @@ static void handle_button_press_event(struct slot *p_slot)
|
||||||
"press.\n", p_slot->name);
|
"press.\n", p_slot->name);
|
||||||
}
|
}
|
||||||
/* blink green LED and turn off amber */
|
/* blink green LED and turn off amber */
|
||||||
if (PWR_LED(ctrl->ctrlcap))
|
if (PWR_LED(ctrl))
|
||||||
p_slot->hpc_ops->green_led_blink(p_slot);
|
p_slot->hpc_ops->green_led_blink(p_slot);
|
||||||
if (ATTN_LED(ctrl->ctrlcap))
|
if (ATTN_LED(ctrl))
|
||||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||||
|
|
||||||
schedule_delayed_work(&p_slot->work, 5*HZ);
|
schedule_delayed_work(&p_slot->work, 5*HZ);
|
||||||
|
@ -427,13 +427,13 @@ static void handle_button_press_event(struct slot *p_slot)
|
||||||
dbg("%s: button cancel\n", __func__);
|
dbg("%s: button cancel\n", __func__);
|
||||||
cancel_delayed_work(&p_slot->work);
|
cancel_delayed_work(&p_slot->work);
|
||||||
if (p_slot->state == BLINKINGOFF_STATE) {
|
if (p_slot->state == BLINKINGOFF_STATE) {
|
||||||
if (PWR_LED(ctrl->ctrlcap))
|
if (PWR_LED(ctrl))
|
||||||
p_slot->hpc_ops->green_led_on(p_slot);
|
p_slot->hpc_ops->green_led_on(p_slot);
|
||||||
} else {
|
} else {
|
||||||
if (PWR_LED(ctrl->ctrlcap))
|
if (PWR_LED(ctrl))
|
||||||
p_slot->hpc_ops->green_led_off(p_slot);
|
p_slot->hpc_ops->green_led_off(p_slot);
|
||||||
}
|
}
|
||||||
if (ATTN_LED(ctrl->ctrlcap))
|
if (ATTN_LED(ctrl))
|
||||||
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
p_slot->hpc_ops->set_attention_status(p_slot, 0);
|
||||||
info("PCI slot #%s - action canceled due to button press\n",
|
info("PCI slot #%s - action canceled due to button press\n",
|
||||||
p_slot->name);
|
p_slot->name);
|
||||||
|
@ -492,16 +492,16 @@ static void interrupt_event_handler(struct work_struct *work)
|
||||||
handle_button_press_event(p_slot);
|
handle_button_press_event(p_slot);
|
||||||
break;
|
break;
|
||||||
case INT_POWER_FAULT:
|
case INT_POWER_FAULT:
|
||||||
if (!POWER_CTRL(ctrl->ctrlcap))
|
if (!POWER_CTRL(ctrl))
|
||||||
break;
|
break;
|
||||||
if (ATTN_LED(ctrl->ctrlcap))
|
if (ATTN_LED(ctrl))
|
||||||
p_slot->hpc_ops->set_attention_status(p_slot, 1);
|
p_slot->hpc_ops->set_attention_status(p_slot, 1);
|
||||||
if (PWR_LED(ctrl->ctrlcap))
|
if (PWR_LED(ctrl))
|
||||||
p_slot->hpc_ops->green_led_off(p_slot);
|
p_slot->hpc_ops->green_led_off(p_slot);
|
||||||
break;
|
break;
|
||||||
case INT_PRESENCE_ON:
|
case INT_PRESENCE_ON:
|
||||||
case INT_PRESENCE_OFF:
|
case INT_PRESENCE_OFF:
|
||||||
if (!HP_SUPR_RM(ctrl->ctrlcap))
|
if (!HP_SUPR_RM(ctrl))
|
||||||
break;
|
break;
|
||||||
dbg("Surprise Removal\n");
|
dbg("Surprise Removal\n");
|
||||||
update_slot_info(p_slot);
|
update_slot_info(p_slot);
|
||||||
|
@ -531,7 +531,7 @@ int pciehp_enable_slot(struct slot *p_slot)
|
||||||
mutex_unlock(&p_slot->ctrl->crit_sect);
|
mutex_unlock(&p_slot->ctrl->crit_sect);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
|
if (MRL_SENS(p_slot->ctrl)) {
|
||||||
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
rc = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||||
if (rc || getstatus) {
|
if (rc || getstatus) {
|
||||||
info("%s: latch open on slot(%s)\n", __func__,
|
info("%s: latch open on slot(%s)\n", __func__,
|
||||||
|
@ -541,7 +541,7 @@ int pciehp_enable_slot(struct slot *p_slot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
|
if (POWER_CTRL(p_slot->ctrl)) {
|
||||||
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
rc = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||||
if (rc || getstatus) {
|
if (rc || getstatus) {
|
||||||
info("%s: already enabled on slot(%s)\n", __func__,
|
info("%s: already enabled on slot(%s)\n", __func__,
|
||||||
|
@ -576,7 +576,7 @@ int pciehp_disable_slot(struct slot *p_slot)
|
||||||
/* Check to see if (latch closed, card present, power on) */
|
/* Check to see if (latch closed, card present, power on) */
|
||||||
mutex_lock(&p_slot->ctrl->crit_sect);
|
mutex_lock(&p_slot->ctrl->crit_sect);
|
||||||
|
|
||||||
if (!HP_SUPR_RM(p_slot->ctrl->ctrlcap)) {
|
if (!HP_SUPR_RM(p_slot->ctrl)) {
|
||||||
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
|
ret = p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
|
||||||
if (ret || !getstatus) {
|
if (ret || !getstatus) {
|
||||||
info("%s: no adapter on slot(%s)\n", __func__,
|
info("%s: no adapter on slot(%s)\n", __func__,
|
||||||
|
@ -586,7 +586,7 @@ int pciehp_disable_slot(struct slot *p_slot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MRL_SENS(p_slot->ctrl->ctrlcap)) {
|
if (MRL_SENS(p_slot->ctrl)) {
|
||||||
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
ret = p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
|
||||||
if (ret || getstatus) {
|
if (ret || getstatus) {
|
||||||
info("%s: latch open on slot(%s)\n", __func__,
|
info("%s: latch open on slot(%s)\n", __func__,
|
||||||
|
@ -596,7 +596,7 @@ int pciehp_disable_slot(struct slot *p_slot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (POWER_CTRL(p_slot->ctrl->ctrlcap)) {
|
if (POWER_CTRL(p_slot->ctrl)) {
|
||||||
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
ret = p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
|
||||||
if (ret || !getstatus) {
|
if (ret || !getstatus) {
|
||||||
info("%s: already disabled slot(%s)\n", __func__,
|
info("%s: already disabled slot(%s)\n", __func__,
|
||||||
|
|
|
@ -221,6 +221,32 @@ static void start_int_poll_timer(struct controller *ctrl, int sec)
|
||||||
add_timer(&ctrl->poll_timer);
|
add_timer(&ctrl->poll_timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int pciehp_request_irq(struct controller *ctrl)
|
||||||
|
{
|
||||||
|
int retval, irq = ctrl->pci_dev->irq;
|
||||||
|
|
||||||
|
/* Install interrupt polling timer. Start with 10 sec delay */
|
||||||
|
if (pciehp_poll_mode) {
|
||||||
|
init_timer(&ctrl->poll_timer);
|
||||||
|
start_int_poll_timer(ctrl, 10);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Installs the interrupt handler */
|
||||||
|
retval = request_irq(irq, pcie_isr, IRQF_SHARED, MY_NAME, ctrl);
|
||||||
|
if (retval)
|
||||||
|
err("Cannot get irq %d for the hotplug controller\n", irq);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void pciehp_free_irq(struct controller *ctrl)
|
||||||
|
{
|
||||||
|
if (pciehp_poll_mode)
|
||||||
|
del_timer_sync(&ctrl->poll_timer);
|
||||||
|
else
|
||||||
|
free_irq(ctrl->pci_dev->irq, ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int pcie_wait_cmd(struct controller *ctrl)
|
static inline int pcie_wait_cmd(struct controller *ctrl)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
@ -242,17 +268,15 @@ static inline int pcie_wait_cmd(struct controller *ctrl)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pcie_write_cmd - Issue controller command
|
* pcie_write_cmd - Issue controller command
|
||||||
* @slot: slot to which the command is issued
|
* @ctrl: controller to which the command is issued
|
||||||
* @cmd: command value written to slot control register
|
* @cmd: command value written to slot control register
|
||||||
* @mask: bitmask of slot control register to be modified
|
* @mask: bitmask of slot control register to be modified
|
||||||
*/
|
*/
|
||||||
static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
|
static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
|
||||||
{
|
{
|
||||||
struct controller *ctrl = slot->ctrl;
|
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
u16 slot_status;
|
u16 slot_status;
|
||||||
u16 slot_ctrl;
|
u16 slot_ctrl;
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
mutex_lock(&ctrl->ctrl_lock);
|
mutex_lock(&ctrl->ctrl_lock);
|
||||||
|
|
||||||
|
@ -270,24 +294,24 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask)
|
||||||
__func__);
|
__func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&ctrl->lock, flags);
|
|
||||||
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
|
retval = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
err("%s: Cannot read SLOTCTRL register\n", __func__);
|
err("%s: Cannot read SLOTCTRL register\n", __func__);
|
||||||
goto out_spin_unlock;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot_ctrl &= ~mask;
|
slot_ctrl &= ~mask;
|
||||||
slot_ctrl |= ((cmd & mask) | CMD_CMPL_INTR_ENABLE);
|
slot_ctrl |= (cmd & mask);
|
||||||
|
/* Don't enable command completed if caller is changing it. */
|
||||||
|
if (!(mask & CMD_CMPL_INTR_ENABLE))
|
||||||
|
slot_ctrl |= CMD_CMPL_INTR_ENABLE;
|
||||||
|
|
||||||
ctrl->cmd_busy = 1;
|
ctrl->cmd_busy = 1;
|
||||||
|
smp_mb();
|
||||||
retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
|
retval = pciehp_writew(ctrl, SLOTCTRL, slot_ctrl);
|
||||||
if (retval)
|
if (retval)
|
||||||
err("%s: Cannot write to SLOTCTRL register\n", __func__);
|
err("%s: Cannot write to SLOTCTRL register\n", __func__);
|
||||||
|
|
||||||
out_spin_unlock:
|
|
||||||
spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Wait for command completion.
|
* Wait for command completion.
|
||||||
*/
|
*/
|
||||||
|
@ -467,12 +491,7 @@ static int hpc_toggle_emi(struct slot *slot)
|
||||||
|
|
||||||
slot_cmd = EMI_CTRL;
|
slot_cmd = EMI_CTRL;
|
||||||
cmd_mask = EMI_CTRL;
|
cmd_mask = EMI_CTRL;
|
||||||
if (!pciehp_poll_mode) {
|
rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
|
||||||
slot_cmd = slot_cmd | HP_INTR_ENABLE;
|
|
||||||
cmd_mask = cmd_mask | HP_INTR_ENABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
|
||||||
slot->last_emi_toggle = get_seconds();
|
slot->last_emi_toggle = get_seconds();
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -499,12 +518,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!pciehp_poll_mode) {
|
rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||||
slot_cmd = slot_cmd | HP_INTR_ENABLE;
|
|
||||||
cmd_mask = cmd_mask | HP_INTR_ENABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
|
||||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||||
|
|
||||||
|
@ -519,13 +533,7 @@ static void hpc_set_green_led_on(struct slot *slot)
|
||||||
|
|
||||||
slot_cmd = 0x0100;
|
slot_cmd = 0x0100;
|
||||||
cmd_mask = PWR_LED_CTRL;
|
cmd_mask = PWR_LED_CTRL;
|
||||||
if (!pciehp_poll_mode) {
|
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||||
slot_cmd = slot_cmd | HP_INTR_ENABLE;
|
|
||||||
cmd_mask = cmd_mask | HP_INTR_ENABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
|
||||||
|
|
||||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||||
}
|
}
|
||||||
|
@ -538,12 +546,7 @@ static void hpc_set_green_led_off(struct slot *slot)
|
||||||
|
|
||||||
slot_cmd = 0x0300;
|
slot_cmd = 0x0300;
|
||||||
cmd_mask = PWR_LED_CTRL;
|
cmd_mask = PWR_LED_CTRL;
|
||||||
if (!pciehp_poll_mode) {
|
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||||
slot_cmd = slot_cmd | HP_INTR_ENABLE;
|
|
||||||
cmd_mask = cmd_mask | HP_INTR_ENABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
|
||||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||||
}
|
}
|
||||||
|
@ -556,23 +559,19 @@ static void hpc_set_green_led_blink(struct slot *slot)
|
||||||
|
|
||||||
slot_cmd = 0x0200;
|
slot_cmd = 0x0200;
|
||||||
cmd_mask = PWR_LED_CTRL;
|
cmd_mask = PWR_LED_CTRL;
|
||||||
if (!pciehp_poll_mode) {
|
pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||||
slot_cmd = slot_cmd | HP_INTR_ENABLE;
|
|
||||||
cmd_mask = cmd_mask | HP_INTR_ENABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
|
||||||
|
|
||||||
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
dbg("%s: SLOTCTRL %x write cmd %x\n",
|
||||||
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
__func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hpc_release_ctlr(struct controller *ctrl)
|
static void hpc_release_ctlr(struct controller *ctrl)
|
||||||
{
|
{
|
||||||
if (pciehp_poll_mode)
|
/* Mask Hot-plug Interrupt Enable */
|
||||||
del_timer(&ctrl->poll_timer);
|
if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE))
|
||||||
else
|
err("%s: Cannot mask hotplut interrupt enable\n", __func__);
|
||||||
free_irq(ctrl->pci_dev->irq, ctrl);
|
|
||||||
|
/* Free interrupt handler or interrupt polling timer */
|
||||||
|
pciehp_free_irq(ctrl);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is the last controller to be released, destroy the
|
* If this is the last controller to be released, destroy the
|
||||||
|
@ -612,19 +611,13 @@ static int hpc_power_on_slot(struct slot * slot)
|
||||||
cmd_mask = PWR_CTRL;
|
cmd_mask = PWR_CTRL;
|
||||||
/* Enable detection that we turned off at slot power-off time */
|
/* Enable detection that we turned off at slot power-off time */
|
||||||
if (!pciehp_poll_mode) {
|
if (!pciehp_poll_mode) {
|
||||||
slot_cmd = slot_cmd |
|
slot_cmd |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
|
||||||
PWR_FAULT_DETECT_ENABLE |
|
PRSN_DETECT_ENABLE);
|
||||||
MRL_DETECT_ENABLE |
|
cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
|
||||||
PRSN_DETECT_ENABLE |
|
PRSN_DETECT_ENABLE);
|
||||||
HP_INTR_ENABLE;
|
|
||||||
cmd_mask = cmd_mask |
|
|
||||||
PWR_FAULT_DETECT_ENABLE |
|
|
||||||
MRL_DETECT_ENABLE |
|
|
||||||
PRSN_DETECT_ENABLE |
|
|
||||||
HP_INTR_ENABLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||||
|
|
||||||
if (retval) {
|
if (retval) {
|
||||||
err("%s: Write %x command failed!\n", __func__, slot_cmd);
|
err("%s: Write %x command failed!\n", __func__, slot_cmd);
|
||||||
|
@ -697,18 +690,13 @@ static int hpc_power_off_slot(struct slot * slot)
|
||||||
* till the slot is powered on again.
|
* till the slot is powered on again.
|
||||||
*/
|
*/
|
||||||
if (!pciehp_poll_mode) {
|
if (!pciehp_poll_mode) {
|
||||||
slot_cmd = (slot_cmd &
|
slot_cmd &= ~(PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
|
||||||
~PWR_FAULT_DETECT_ENABLE &
|
PRSN_DETECT_ENABLE);
|
||||||
~MRL_DETECT_ENABLE &
|
cmd_mask |= (PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE |
|
||||||
~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE;
|
PRSN_DETECT_ENABLE);
|
||||||
cmd_mask = cmd_mask |
|
|
||||||
PWR_FAULT_DETECT_ENABLE |
|
|
||||||
MRL_DETECT_ENABLE |
|
|
||||||
PRSN_DETECT_ENABLE |
|
|
||||||
HP_INTR_ENABLE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retval = pcie_write_cmd(slot, slot_cmd, cmd_mask);
|
retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
|
||||||
if (retval) {
|
if (retval) {
|
||||||
err("%s: Write command failed!\n", __func__);
|
err("%s: Write command failed!\n", __func__);
|
||||||
retval = -1;
|
retval = -1;
|
||||||
|
@ -733,139 +721,56 @@ static int hpc_power_off_slot(struct slot * slot)
|
||||||
static irqreturn_t pcie_isr(int irq, void *dev_id)
|
static irqreturn_t pcie_isr(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct controller *ctrl = (struct controller *)dev_id;
|
struct controller *ctrl = (struct controller *)dev_id;
|
||||||
u16 slot_status, intr_detect, intr_loc;
|
u16 detected, intr_loc;
|
||||||
u16 temp_word;
|
|
||||||
int hp_slot = 0; /* only 1 slot per PCI Express port */
|
|
||||||
int rc = 0;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOTSTATUS register\n", __func__);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
intr_detect = (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
|
|
||||||
MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED);
|
|
||||||
|
|
||||||
intr_loc = slot_status & intr_detect;
|
|
||||||
|
|
||||||
/* Check to see if it was our interrupt */
|
|
||||||
if ( !intr_loc )
|
|
||||||
return IRQ_NONE;
|
|
||||||
|
|
||||||
dbg("%s: intr_loc %x\n", __func__, intr_loc);
|
|
||||||
/* Mask Hot-plug Interrupt Enable */
|
|
||||||
if (!pciehp_poll_mode) {
|
|
||||||
spin_lock_irqsave(&ctrl->lock, flags);
|
|
||||||
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOT_CTRL register\n",
|
|
||||||
__func__);
|
|
||||||
spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n",
|
|
||||||
__func__, temp_word);
|
|
||||||
temp_word = (temp_word & ~HP_INTR_ENABLE &
|
|
||||||
~CMD_CMPL_INTR_ENABLE) | 0x00;
|
|
||||||
rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot write to SLOTCTRL register\n",
|
|
||||||
__func__);
|
|
||||||
spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
|
|
||||||
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOT_STATUS register\n",
|
|
||||||
__func__);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n",
|
|
||||||
__func__, slot_status);
|
|
||||||
|
|
||||||
/* Clear command complete interrupt caused by this write */
|
|
||||||
temp_word = 0x1f;
|
|
||||||
rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot write to SLOTSTATUS register\n",
|
|
||||||
__func__);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intr_loc & CMD_COMPLETED) {
|
|
||||||
/*
|
/*
|
||||||
* Command Complete Interrupt Pending
|
* In order to guarantee that all interrupt events are
|
||||||
|
* serviced, we need to re-inspect Slot Status register after
|
||||||
|
* clearing what is presumed to be the last pending interrupt.
|
||||||
*/
|
*/
|
||||||
|
intr_loc = 0;
|
||||||
|
do {
|
||||||
|
if (pciehp_readw(ctrl, SLOTSTATUS, &detected)) {
|
||||||
|
err("%s: Cannot read SLOTSTATUS\n", __func__);
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
detected &= (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED |
|
||||||
|
MRL_SENS_CHANGED | PRSN_DETECT_CHANGED |
|
||||||
|
CMD_COMPLETED);
|
||||||
|
intr_loc |= detected;
|
||||||
|
if (!intr_loc)
|
||||||
|
return IRQ_NONE;
|
||||||
|
if (pciehp_writew(ctrl, SLOTSTATUS, detected)) {
|
||||||
|
err("%s: Cannot write to SLOTSTATUS\n", __func__);
|
||||||
|
return IRQ_NONE;
|
||||||
|
}
|
||||||
|
} while (detected);
|
||||||
|
|
||||||
|
dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc);
|
||||||
|
|
||||||
|
/* Check Command Complete Interrupt Pending */
|
||||||
|
if (intr_loc & CMD_COMPLETED) {
|
||||||
ctrl->cmd_busy = 0;
|
ctrl->cmd_busy = 0;
|
||||||
|
smp_mb();
|
||||||
wake_up_interruptible(&ctrl->queue);
|
wake_up_interruptible(&ctrl->queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check MRL Sensor Changed */
|
||||||
if (intr_loc & MRL_SENS_CHANGED)
|
if (intr_loc & MRL_SENS_CHANGED)
|
||||||
pciehp_handle_switch_change(hp_slot, ctrl);
|
pciehp_handle_switch_change(0, ctrl);
|
||||||
|
|
||||||
|
/* Check Attention Button Pressed */
|
||||||
if (intr_loc & ATTN_BUTTN_PRESSED)
|
if (intr_loc & ATTN_BUTTN_PRESSED)
|
||||||
pciehp_handle_attention_button(hp_slot, ctrl);
|
pciehp_handle_attention_button(0, ctrl);
|
||||||
|
|
||||||
|
/* Check Presence Detect Changed */
|
||||||
if (intr_loc & PRSN_DETECT_CHANGED)
|
if (intr_loc & PRSN_DETECT_CHANGED)
|
||||||
pciehp_handle_presence_change(hp_slot, ctrl);
|
pciehp_handle_presence_change(0, ctrl);
|
||||||
|
|
||||||
|
/* Check Power Fault Detected */
|
||||||
if (intr_loc & PWR_FAULT_DETECTED)
|
if (intr_loc & PWR_FAULT_DETECTED)
|
||||||
pciehp_handle_power_fault(hp_slot, ctrl);
|
pciehp_handle_power_fault(0, ctrl);
|
||||||
|
|
||||||
/* Clear all events after serving them */
|
|
||||||
temp_word = 0x1F;
|
|
||||||
rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot write to SLOTSTATUS register\n", __func__);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
/* Unmask Hot-plug Interrupt Enable */
|
|
||||||
if (!pciehp_poll_mode) {
|
|
||||||
spin_lock_irqsave(&ctrl->lock, flags);
|
|
||||||
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOTCTRL register\n",
|
|
||||||
__func__);
|
|
||||||
spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg("%s: Unmask Hot-plug Interrupt Enable\n", __func__);
|
|
||||||
temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
|
|
||||||
|
|
||||||
rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot write to SLOTCTRL register\n",
|
|
||||||
__func__);
|
|
||||||
spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&ctrl->lock, flags);
|
|
||||||
|
|
||||||
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOT_STATUS register\n",
|
|
||||||
__func__);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear command complete interrupt caused by this write */
|
|
||||||
temp_word = 0x1F;
|
|
||||||
rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot write to SLOTSTATUS failed\n",
|
|
||||||
__func__);
|
|
||||||
return IRQ_NONE;
|
|
||||||
}
|
|
||||||
dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n",
|
|
||||||
__func__, temp_word);
|
|
||||||
}
|
|
||||||
|
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
@ -1052,7 +957,7 @@ static struct hpc_ops pciehp_hpc_ops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_ACPI
|
#ifdef CONFIG_ACPI
|
||||||
int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
static int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||||
{
|
{
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
|
acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
|
||||||
|
@ -1112,7 +1017,7 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
err("Cannot get control of hotplug hardware for pci %s\n",
|
dbg("Cannot get control of hotplug hardware for pci %s\n",
|
||||||
pci_name(dev));
|
pci_name(dev));
|
||||||
|
|
||||||
kfree(string.pointer);
|
kfree(string.pointer);
|
||||||
|
@ -1123,45 +1028,9 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
|
||||||
static int pcie_init_hardware_part1(struct controller *ctrl,
|
static int pcie_init_hardware_part1(struct controller *ctrl,
|
||||||
struct pcie_device *dev)
|
struct pcie_device *dev)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
u16 temp_word;
|
|
||||||
u32 slot_cap;
|
|
||||||
u16 slot_status;
|
|
||||||
|
|
||||||
rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOTCAP register\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mask Hot-plug Interrupt Enable */
|
/* Mask Hot-plug Interrupt Enable */
|
||||||
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
|
if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) {
|
||||||
if (rc) {
|
err("%s: Cannot mask hotplug interrupt enable\n", __func__);
|
||||||
err("%s: Cannot read SLOTCTRL register\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg("%s: SLOTCTRL %x value read %x\n",
|
|
||||||
__func__, ctrl->cap_base + SLOTCTRL, temp_word);
|
|
||||||
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
|
|
||||||
0x00;
|
|
||||||
|
|
||||||
rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot write to SLOTCTRL register\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOTSTATUS register\n", __func__);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_word = 0x1F; /* Clear all events */
|
|
||||||
rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot write to SLOTSTATUS register\n", __func__);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1169,205 +1038,125 @@ static int pcie_init_hardware_part1(struct controller *ctrl,
|
||||||
|
|
||||||
int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
|
int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
|
||||||
{
|
{
|
||||||
int rc;
|
u16 cmd, mask;
|
||||||
u16 temp_word;
|
|
||||||
u16 intr_enable = 0;
|
|
||||||
u32 slot_cap;
|
|
||||||
u16 slot_status;
|
|
||||||
|
|
||||||
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOTCTRL register\n", __func__);
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
intr_enable = intr_enable | PRSN_DETECT_ENABLE;
|
|
||||||
|
|
||||||
rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOTCAP register\n", __func__);
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ATTN_BUTTN(slot_cap))
|
|
||||||
intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
|
|
||||||
|
|
||||||
if (POWER_CTRL(slot_cap))
|
|
||||||
intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
|
|
||||||
|
|
||||||
if (MRL_SENS(slot_cap))
|
|
||||||
intr_enable = intr_enable | MRL_DETECT_ENABLE;
|
|
||||||
|
|
||||||
temp_word = (temp_word & ~intr_enable) | intr_enable;
|
|
||||||
|
|
||||||
if (pciehp_poll_mode) {
|
|
||||||
temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
|
|
||||||
} else {
|
|
||||||
temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unmask Hot-plug Interrupt Enable for the interrupt
|
* We need to clear all events before enabling hotplug interrupt
|
||||||
* notification mechanism case.
|
* notification mechanism in order for hotplug controler to
|
||||||
|
* generate interrupts.
|
||||||
*/
|
*/
|
||||||
rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
|
if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
|
||||||
if (rc) {
|
err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
|
||||||
err("%s: Cannot write to SLOTCTRL register\n", __func__);
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd = PRSN_DETECT_ENABLE;
|
||||||
|
if (ATTN_BUTTN(ctrl))
|
||||||
|
cmd |= ATTN_BUTTN_ENABLE;
|
||||||
|
if (POWER_CTRL(ctrl))
|
||||||
|
cmd |= PWR_FAULT_DETECT_ENABLE;
|
||||||
|
if (MRL_SENS(ctrl))
|
||||||
|
cmd |= MRL_DETECT_ENABLE;
|
||||||
|
if (!pciehp_poll_mode)
|
||||||
|
cmd |= HP_INTR_ENABLE;
|
||||||
|
|
||||||
|
mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE |
|
||||||
|
PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | HP_INTR_ENABLE;
|
||||||
|
|
||||||
|
if (pcie_write_cmd(ctrl, cmd, mask)) {
|
||||||
|
err("%s: Cannot enable software notification\n", __func__);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOTSTATUS register\n", __func__);
|
|
||||||
goto abort_disable_intr;
|
|
||||||
}
|
|
||||||
|
|
||||||
temp_word = 0x1F; /* Clear all events */
|
if (pciehp_force)
|
||||||
rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot write to SLOTSTATUS register\n", __func__);
|
|
||||||
goto abort_disable_intr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pciehp_force) {
|
|
||||||
dbg("Bypassing BIOS check for pciehp use on %s\n",
|
dbg("Bypassing BIOS check for pciehp use on %s\n",
|
||||||
pci_name(ctrl->pci_dev));
|
pci_name(ctrl->pci_dev));
|
||||||
} else {
|
else if (pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev))
|
||||||
rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
|
|
||||||
if (rc)
|
|
||||||
goto abort_disable_intr;
|
goto abort_disable_intr;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* We end up here for the many possible ways to fail this API. */
|
/* We end up here for the many possible ways to fail this API. */
|
||||||
abort_disable_intr:
|
abort_disable_intr:
|
||||||
rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
|
if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE))
|
||||||
if (!rc) {
|
|
||||||
temp_word &= ~(intr_enable | HP_INTR_ENABLE);
|
|
||||||
rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
|
|
||||||
}
|
|
||||||
if (rc)
|
|
||||||
err("%s : disabling interrupts failed\n", __func__);
|
err("%s : disabling interrupts failed\n", __func__);
|
||||||
abort:
|
abort:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void dbg_ctrl(struct controller *ctrl)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u16 reg16;
|
||||||
|
struct pci_dev *pdev = ctrl->pci_dev;
|
||||||
|
|
||||||
|
if (!pciehp_debug)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dbg("Hotplug Controller:\n");
|
||||||
|
dbg(" Seg/Bus/Dev/Func/IRQ : %s IRQ %d\n", pci_name(pdev), pdev->irq);
|
||||||
|
dbg(" Vendor ID : 0x%04x\n", pdev->vendor);
|
||||||
|
dbg(" Device ID : 0x%04x\n", pdev->device);
|
||||||
|
dbg(" Subsystem ID : 0x%04x\n", pdev->subsystem_device);
|
||||||
|
dbg(" Subsystem Vendor ID : 0x%04x\n", pdev->subsystem_vendor);
|
||||||
|
dbg(" PCIe Cap offset : 0x%02x\n", ctrl->cap_base);
|
||||||
|
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
|
||||||
|
if (!pci_resource_len(pdev, i))
|
||||||
|
continue;
|
||||||
|
dbg(" PCI resource [%d] : 0x%llx@0x%llx\n", i,
|
||||||
|
(unsigned long long)pci_resource_len(pdev, i),
|
||||||
|
(unsigned long long)pci_resource_start(pdev, i));
|
||||||
|
}
|
||||||
|
dbg("Slot Capabilities : 0x%08x\n", ctrl->slot_cap);
|
||||||
|
dbg(" Physical Slot Number : %d\n", ctrl->first_slot);
|
||||||
|
dbg(" Attention Button : %3s\n", ATTN_BUTTN(ctrl) ? "yes" : "no");
|
||||||
|
dbg(" Power Controller : %3s\n", POWER_CTRL(ctrl) ? "yes" : "no");
|
||||||
|
dbg(" MRL Sensor : %3s\n", MRL_SENS(ctrl) ? "yes" : "no");
|
||||||
|
dbg(" Attention Indicator : %3s\n", ATTN_LED(ctrl) ? "yes" : "no");
|
||||||
|
dbg(" Power Indicator : %3s\n", PWR_LED(ctrl) ? "yes" : "no");
|
||||||
|
dbg(" Hot-Plug Surprise : %3s\n", HP_SUPR_RM(ctrl) ? "yes" : "no");
|
||||||
|
dbg(" EMI Present : %3s\n", EMI(ctrl) ? "yes" : "no");
|
||||||
|
pciehp_readw(ctrl, SLOTSTATUS, ®16);
|
||||||
|
dbg("Slot Status : 0x%04x\n", reg16);
|
||||||
|
pciehp_readw(ctrl, SLOTSTATUS, ®16);
|
||||||
|
dbg("Slot Control : 0x%04x\n", reg16);
|
||||||
|
}
|
||||||
|
|
||||||
int pcie_init(struct controller *ctrl, struct pcie_device *dev)
|
int pcie_init(struct controller *ctrl, struct pcie_device *dev)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
u16 cap_reg;
|
|
||||||
u32 slot_cap;
|
u32 slot_cap;
|
||||||
int cap_base;
|
struct pci_dev *pdev = dev->port;
|
||||||
u16 slot_status, slot_ctrl;
|
|
||||||
struct pci_dev *pdev;
|
|
||||||
|
|
||||||
pdev = dev->port;
|
ctrl->pci_dev = pdev;
|
||||||
ctrl->pci_dev = pdev; /* save pci_dev in context */
|
ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
|
||||||
|
if (!ctrl->cap_base) {
|
||||||
dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
|
err("%s: Cannot find PCI Express capability\n", __func__);
|
||||||
__func__, pdev->vendor, pdev->device);
|
|
||||||
|
|
||||||
cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
|
|
||||||
if (cap_base == 0) {
|
|
||||||
dbg("%s: Can't find PCI_CAP_ID_EXP (0x10)\n", __func__);
|
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
if (pciehp_readl(ctrl, SLOTCAP, &slot_cap)) {
|
||||||
ctrl->cap_base = cap_base;
|
|
||||||
|
|
||||||
dbg("%s: pcie_cap_base %x\n", __func__, cap_base);
|
|
||||||
|
|
||||||
rc = pciehp_readw(ctrl, CAPREG, &cap_reg);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read CAPREG register\n", __func__);
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
dbg("%s: CAPREG offset %x cap_reg %x\n",
|
|
||||||
__func__, ctrl->cap_base + CAPREG, cap_reg);
|
|
||||||
|
|
||||||
if (((cap_reg & SLOT_IMPL) == 0) ||
|
|
||||||
(((cap_reg & DEV_PORT_TYPE) != 0x0040)
|
|
||||||
&& ((cap_reg & DEV_PORT_TYPE) != 0x0060))) {
|
|
||||||
dbg("%s : This is not a root port or the port is not "
|
|
||||||
"connected to a slot\n", __func__);
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOTCAP register\n", __func__);
|
err("%s: Cannot read SLOTCAP register\n", __func__);
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
dbg("%s: SLOTCAP offset %x slot_cap %x\n",
|
|
||||||
__func__, ctrl->cap_base + SLOTCAP, slot_cap);
|
|
||||||
|
|
||||||
if (!(slot_cap & HP_CAP)) {
|
ctrl->slot_cap = slot_cap;
|
||||||
dbg("%s : This slot is not hot-plug capable\n", __func__);
|
ctrl->first_slot = slot_cap >> 19;
|
||||||
goto abort;
|
ctrl->slot_device_offset = 0;
|
||||||
}
|
ctrl->num_slots = 1;
|
||||||
/* For debugging purpose */
|
ctrl->hpc_ops = &pciehp_hpc_ops;
|
||||||
rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
|
mutex_init(&ctrl->crit_sect);
|
||||||
if (rc) {
|
mutex_init(&ctrl->ctrl_lock);
|
||||||
err("%s: Cannot read SLOTSTATUS register\n", __func__);
|
init_waitqueue_head(&ctrl->queue);
|
||||||
goto abort;
|
dbg_ctrl(ctrl);
|
||||||
}
|
|
||||||
dbg("%s: SLOTSTATUS offset %x slot_status %x\n",
|
|
||||||
__func__, ctrl->cap_base + SLOTSTATUS, slot_status);
|
|
||||||
|
|
||||||
rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl);
|
|
||||||
if (rc) {
|
|
||||||
err("%s: Cannot read SLOTCTRL register\n", __func__);
|
|
||||||
goto abort;
|
|
||||||
}
|
|
||||||
dbg("%s: SLOTCTRL offset %x slot_ctrl %x\n",
|
|
||||||
__func__, ctrl->cap_base + SLOTCTRL, slot_ctrl);
|
|
||||||
|
|
||||||
for (rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
|
|
||||||
if (pci_resource_len(pdev, rc) > 0)
|
|
||||||
dbg("pci resource[%d] start=0x%llx(len=0x%llx)\n", rc,
|
|
||||||
(unsigned long long)pci_resource_start(pdev, rc),
|
|
||||||
(unsigned long long)pci_resource_len(pdev, rc));
|
|
||||||
|
|
||||||
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
|
info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
|
||||||
pdev->vendor, pdev->device,
|
pdev->vendor, pdev->device,
|
||||||
pdev->subsystem_vendor, pdev->subsystem_device);
|
pdev->subsystem_vendor, pdev->subsystem_device);
|
||||||
|
|
||||||
mutex_init(&ctrl->crit_sect);
|
if (pcie_init_hardware_part1(ctrl, dev))
|
||||||
mutex_init(&ctrl->ctrl_lock);
|
|
||||||
spin_lock_init(&ctrl->lock);
|
|
||||||
|
|
||||||
/* setup wait queue */
|
|
||||||
init_waitqueue_head(&ctrl->queue);
|
|
||||||
|
|
||||||
/* return PCI Controller Info */
|
|
||||||
ctrl->slot_device_offset = 0;
|
|
||||||
ctrl->num_slots = 1;
|
|
||||||
ctrl->first_slot = slot_cap >> 19;
|
|
||||||
ctrl->ctrlcap = slot_cap & 0x0000007f;
|
|
||||||
|
|
||||||
rc = pcie_init_hardware_part1(ctrl, dev);
|
|
||||||
if (rc)
|
|
||||||
goto abort;
|
goto abort;
|
||||||
|
|
||||||
if (pciehp_poll_mode) {
|
if (pciehp_request_irq(ctrl))
|
||||||
/* Install interrupt polling timer. Start with 10 sec delay */
|
|
||||||
init_timer(&ctrl->poll_timer);
|
|
||||||
start_int_poll_timer(ctrl, 10);
|
|
||||||
} else {
|
|
||||||
/* Installs the interrupt handler */
|
|
||||||
rc = request_irq(ctrl->pci_dev->irq, pcie_isr, IRQF_SHARED,
|
|
||||||
MY_NAME, (void *)ctrl);
|
|
||||||
dbg("%s: request_irq %d for hpc%d (returns %d)\n",
|
|
||||||
__func__, ctrl->pci_dev->irq,
|
|
||||||
atomic_read(&pciehp_num_controllers), rc);
|
|
||||||
if (rc) {
|
|
||||||
err("Can't get irq %d for the hotplug controller\n",
|
|
||||||
ctrl->pci_dev->irq);
|
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
|
||||||
}
|
|
||||||
dbg("pciehp ctrl b:d:f:irq=0x%x:%x:%x:%x\n", pdev->bus->number,
|
|
||||||
PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If this is the first controller to be initialized,
|
* If this is the first controller to be initialized,
|
||||||
|
@ -1376,21 +1165,17 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
|
||||||
if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
|
if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
|
||||||
pciehp_wq = create_singlethread_workqueue("pciehpd");
|
pciehp_wq = create_singlethread_workqueue("pciehpd");
|
||||||
if (!pciehp_wq) {
|
if (!pciehp_wq) {
|
||||||
rc = -ENOMEM;
|
|
||||||
goto abort_free_irq;
|
goto abort_free_irq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = pcie_init_hardware_part2(ctrl, dev);
|
if (pcie_init_hardware_part2(ctrl, dev))
|
||||||
if (rc == 0) {
|
goto abort_free_irq;
|
||||||
ctrl->hpc_ops = &pciehp_hpc_ops;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
abort_free_irq:
|
abort_free_irq:
|
||||||
if (pciehp_poll_mode)
|
pciehp_free_irq(ctrl);
|
||||||
del_timer_sync(&ctrl->poll_timer);
|
|
||||||
else
|
|
||||||
free_irq(ctrl->pci_dev->irq, ctrl);
|
|
||||||
abort:
|
abort:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
int shpchp_debug;
|
int shpchp_debug;
|
||||||
int shpchp_poll_mode;
|
int shpchp_poll_mode;
|
||||||
int shpchp_poll_time;
|
int shpchp_poll_time;
|
||||||
|
int shpchp_slot_with_bus;
|
||||||
struct workqueue_struct *shpchp_wq;
|
struct workqueue_struct *shpchp_wq;
|
||||||
|
|
||||||
#define DRIVER_VERSION "0.4"
|
#define DRIVER_VERSION "0.4"
|
||||||
|
@ -52,9 +53,11 @@ MODULE_LICENSE("GPL");
|
||||||
module_param(shpchp_debug, bool, 0644);
|
module_param(shpchp_debug, bool, 0644);
|
||||||
module_param(shpchp_poll_mode, bool, 0644);
|
module_param(shpchp_poll_mode, bool, 0644);
|
||||||
module_param(shpchp_poll_time, int, 0644);
|
module_param(shpchp_poll_time, int, 0644);
|
||||||
|
module_param(shpchp_slot_with_bus, bool, 0644);
|
||||||
MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
|
MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");
|
||||||
MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
|
MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");
|
||||||
MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
|
MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");
|
||||||
|
MODULE_PARM_DESC(shpchp_slot_with_bus, "Use bus number in the slot name");
|
||||||
|
|
||||||
#define SHPC_MODULE_NAME "shpchp"
|
#define SHPC_MODULE_NAME "shpchp"
|
||||||
|
|
||||||
|
@ -100,8 +103,12 @@ static void release_slot(struct hotplug_slot *hotplug_slot)
|
||||||
|
|
||||||
static void make_slot_name(struct slot *slot)
|
static void make_slot_name(struct slot *slot)
|
||||||
{
|
{
|
||||||
|
if (shpchp_slot_with_bus)
|
||||||
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
|
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
|
||||||
slot->bus, slot->number);
|
slot->bus, slot->number);
|
||||||
|
else
|
||||||
|
snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
|
||||||
|
slot->number);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int init_slots(struct controller *ctrl)
|
static int init_slots(struct controller *ctrl)
|
||||||
|
|
|
@ -123,7 +123,7 @@ static void msix_flush_writes(unsigned int irq)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msi_set_mask_bit(unsigned int irq, int flag)
|
static void msi_set_mask_bits(unsigned int irq, u32 mask, u32 flag)
|
||||||
{
|
{
|
||||||
struct msi_desc *entry;
|
struct msi_desc *entry;
|
||||||
|
|
||||||
|
@ -137,8 +137,8 @@ static void msi_set_mask_bit(unsigned int irq, int flag)
|
||||||
|
|
||||||
pos = (long)entry->mask_base;
|
pos = (long)entry->mask_base;
|
||||||
pci_read_config_dword(entry->dev, pos, &mask_bits);
|
pci_read_config_dword(entry->dev, pos, &mask_bits);
|
||||||
mask_bits &= ~(1);
|
mask_bits &= ~(mask);
|
||||||
mask_bits |= flag;
|
mask_bits |= flag & mask;
|
||||||
pci_write_config_dword(entry->dev, pos, mask_bits);
|
pci_write_config_dword(entry->dev, pos, mask_bits);
|
||||||
} else {
|
} else {
|
||||||
msi_set_enable(entry->dev, !flag);
|
msi_set_enable(entry->dev, !flag);
|
||||||
|
@ -241,13 +241,13 @@ void write_msi_msg(unsigned int irq, struct msi_msg *msg)
|
||||||
|
|
||||||
void mask_msi_irq(unsigned int irq)
|
void mask_msi_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
msi_set_mask_bit(irq, 1);
|
msi_set_mask_bits(irq, 1, 1);
|
||||||
msix_flush_writes(irq);
|
msix_flush_writes(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unmask_msi_irq(unsigned int irq)
|
void unmask_msi_irq(unsigned int irq)
|
||||||
{
|
{
|
||||||
msi_set_mask_bit(irq, 0);
|
msi_set_mask_bits(irq, 1, 0);
|
||||||
msix_flush_writes(irq);
|
msix_flush_writes(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,7 +291,8 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
|
||||||
msi_set_enable(dev, 0);
|
msi_set_enable(dev, 0);
|
||||||
write_msi_msg(dev->irq, &entry->msg);
|
write_msi_msg(dev->irq, &entry->msg);
|
||||||
if (entry->msi_attrib.maskbit)
|
if (entry->msi_attrib.maskbit)
|
||||||
msi_set_mask_bit(dev->irq, entry->msi_attrib.masked);
|
msi_set_mask_bits(dev->irq, entry->msi_attrib.maskbits_mask,
|
||||||
|
entry->msi_attrib.masked);
|
||||||
|
|
||||||
pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
|
pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
|
||||||
control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
|
control &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
|
||||||
|
@ -315,7 +316,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
|
||||||
|
|
||||||
list_for_each_entry(entry, &dev->msi_list, list) {
|
list_for_each_entry(entry, &dev->msi_list, list) {
|
||||||
write_msi_msg(entry->irq, &entry->msg);
|
write_msi_msg(entry->irq, &entry->msg);
|
||||||
msi_set_mask_bit(entry->irq, entry->msi_attrib.masked);
|
msi_set_mask_bits(entry->irq, 1, entry->msi_attrib.masked);
|
||||||
}
|
}
|
||||||
|
|
||||||
BUG_ON(list_empty(&dev->msi_list));
|
BUG_ON(list_empty(&dev->msi_list));
|
||||||
|
@ -382,6 +383,7 @@ static int msi_capability_init(struct pci_dev *dev)
|
||||||
pci_write_config_dword(dev,
|
pci_write_config_dword(dev,
|
||||||
msi_mask_bits_reg(pos, is_64bit_address(control)),
|
msi_mask_bits_reg(pos, is_64bit_address(control)),
|
||||||
maskbits);
|
maskbits);
|
||||||
|
entry->msi_attrib.maskbits_mask = temp;
|
||||||
}
|
}
|
||||||
list_add_tail(&entry->list, &dev->msi_list);
|
list_add_tail(&entry->list, &dev->msi_list);
|
||||||
|
|
||||||
|
@ -569,10 +571,9 @@ int pci_enable_msi(struct pci_dev* dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pci_enable_msi);
|
EXPORT_SYMBOL(pci_enable_msi);
|
||||||
|
|
||||||
void pci_disable_msi(struct pci_dev* dev)
|
void pci_msi_shutdown(struct pci_dev* dev)
|
||||||
{
|
{
|
||||||
struct msi_desc *entry;
|
struct msi_desc *entry;
|
||||||
int default_irq;
|
|
||||||
|
|
||||||
if (!pci_msi_enable || !dev || !dev->msi_enabled)
|
if (!pci_msi_enable || !dev || !dev->msi_enabled)
|
||||||
return;
|
return;
|
||||||
|
@ -583,15 +584,31 @@ void pci_disable_msi(struct pci_dev* dev)
|
||||||
|
|
||||||
BUG_ON(list_empty(&dev->msi_list));
|
BUG_ON(list_empty(&dev->msi_list));
|
||||||
entry = list_entry(dev->msi_list.next, struct msi_desc, list);
|
entry = list_entry(dev->msi_list.next, struct msi_desc, list);
|
||||||
if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI) {
|
/* Return the the pci reset with msi irqs unmasked */
|
||||||
return;
|
if (entry->msi_attrib.maskbit) {
|
||||||
|
u32 mask = entry->msi_attrib.maskbits_mask;
|
||||||
|
msi_set_mask_bits(dev->irq, mask, ~mask);
|
||||||
}
|
}
|
||||||
|
if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
|
||||||
default_irq = entry->msi_attrib.default_irq;
|
return;
|
||||||
msi_free_irqs(dev);
|
|
||||||
|
|
||||||
/* Restore dev->irq to its default pin-assertion irq */
|
/* Restore dev->irq to its default pin-assertion irq */
|
||||||
dev->irq = default_irq;
|
dev->irq = entry->msi_attrib.default_irq;
|
||||||
|
}
|
||||||
|
void pci_disable_msi(struct pci_dev* dev)
|
||||||
|
{
|
||||||
|
struct msi_desc *entry;
|
||||||
|
|
||||||
|
if (!pci_msi_enable || !dev || !dev->msi_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pci_msi_shutdown(dev);
|
||||||
|
|
||||||
|
entry = list_entry(dev->msi_list.next, struct msi_desc, list);
|
||||||
|
if (!entry->dev || entry->msi_attrib.type != PCI_CAP_ID_MSI)
|
||||||
|
return;
|
||||||
|
|
||||||
|
msi_free_irqs(dev);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pci_disable_msi);
|
EXPORT_SYMBOL(pci_disable_msi);
|
||||||
|
|
||||||
|
@ -684,7 +701,7 @@ static void msix_free_all_irqs(struct pci_dev *dev)
|
||||||
msi_free_irqs(dev);
|
msi_free_irqs(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pci_disable_msix(struct pci_dev* dev)
|
void pci_msix_shutdown(struct pci_dev* dev)
|
||||||
{
|
{
|
||||||
if (!pci_msi_enable || !dev || !dev->msix_enabled)
|
if (!pci_msi_enable || !dev || !dev->msix_enabled)
|
||||||
return;
|
return;
|
||||||
|
@ -692,6 +709,13 @@ void pci_disable_msix(struct pci_dev* dev)
|
||||||
msix_set_enable(dev, 0);
|
msix_set_enable(dev, 0);
|
||||||
pci_intx_for_msi(dev, 1);
|
pci_intx_for_msi(dev, 1);
|
||||||
dev->msix_enabled = 0;
|
dev->msix_enabled = 0;
|
||||||
|
}
|
||||||
|
void pci_disable_msix(struct pci_dev* dev)
|
||||||
|
{
|
||||||
|
if (!pci_msi_enable || !dev || !dev->msix_enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pci_msix_shutdown(dev);
|
||||||
|
|
||||||
msix_free_all_irqs(dev);
|
msix_free_all_irqs(dev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -360,6 +360,8 @@ static void pci_device_shutdown(struct device *dev)
|
||||||
|
|
||||||
if (drv && drv->shutdown)
|
if (drv && drv->shutdown)
|
||||||
drv->shutdown(pci_dev);
|
drv->shutdown(pci_dev);
|
||||||
|
pci_msi_shutdown(pci_dev);
|
||||||
|
pci_msix_shutdown(pci_dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,7 +33,7 @@ source "drivers/pci/pcie/aer/Kconfig"
|
||||||
config PCIEASPM
|
config PCIEASPM
|
||||||
bool "PCI Express ASPM support(Experimental)"
|
bool "PCI Express ASPM support(Experimental)"
|
||||||
depends on PCI && EXPERIMENTAL && PCIEPORTBUS
|
depends on PCI && EXPERIMENTAL && PCIEPORTBUS
|
||||||
default y
|
default n
|
||||||
help
|
help
|
||||||
This enables PCI Express ASPM (Active State Power Management) and
|
This enables PCI Express ASPM (Active State Power Management) and
|
||||||
Clock Power Management. ASPM supports state L0/L0s/L1.
|
Clock Power Management. ASPM supports state L0/L0s/L1.
|
||||||
|
|
|
@ -22,6 +22,7 @@ struct msi_desc {
|
||||||
__u8 masked : 1;
|
__u8 masked : 1;
|
||||||
__u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
|
__u8 is_64 : 1; /* Address size: 0=32bit 1=64bit */
|
||||||
__u8 pos; /* Location of the msi capability */
|
__u8 pos; /* Location of the msi capability */
|
||||||
|
__u32 maskbits_mask; /* mask bits mask */
|
||||||
__u16 entry_nr; /* specific enabled entry */
|
__u16 entry_nr; /* specific enabled entry */
|
||||||
unsigned default_irq; /* default pre-assigned irq */
|
unsigned default_irq; /* default pre-assigned irq */
|
||||||
}msi_attrib;
|
}msi_attrib;
|
||||||
|
|
|
@ -20,8 +20,6 @@
|
||||||
/* Include the pci register defines */
|
/* Include the pci register defines */
|
||||||
#include <linux/pci_regs.h>
|
#include <linux/pci_regs.h>
|
||||||
|
|
||||||
struct pci_vpd;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The PCI interface treats multi-function devices as independent
|
* The PCI interface treats multi-function devices as independent
|
||||||
* devices. The slot/function address of each device is encoded
|
* devices. The slot/function address of each device is encoded
|
||||||
|
@ -131,6 +129,8 @@ struct pci_cap_saved_state {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pcie_link_state;
|
struct pcie_link_state;
|
||||||
|
struct pci_vpd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The pci_dev structure is used to describe PCI devices.
|
* The pci_dev structure is used to describe PCI devices.
|
||||||
*/
|
*/
|
||||||
|
@ -702,6 +702,8 @@ static inline int pci_enable_msi(struct pci_dev *dev)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void pci_msi_shutdown(struct pci_dev *dev)
|
||||||
|
{ }
|
||||||
static inline void pci_disable_msi(struct pci_dev *dev)
|
static inline void pci_disable_msi(struct pci_dev *dev)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -711,6 +713,8 @@ static inline int pci_enable_msix(struct pci_dev *dev,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void pci_msix_shutdown(struct pci_dev *dev)
|
||||||
|
{ }
|
||||||
static inline void pci_disable_msix(struct pci_dev *dev)
|
static inline void pci_disable_msix(struct pci_dev *dev)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
@ -721,9 +725,11 @@ static inline void pci_restore_msi_state(struct pci_dev *dev)
|
||||||
{ }
|
{ }
|
||||||
#else
|
#else
|
||||||
extern int pci_enable_msi(struct pci_dev *dev);
|
extern int pci_enable_msi(struct pci_dev *dev);
|
||||||
|
extern void pci_msi_shutdown(struct pci_dev *dev);
|
||||||
extern void pci_disable_msi(struct pci_dev *dev);
|
extern void pci_disable_msi(struct pci_dev *dev);
|
||||||
extern int pci_enable_msix(struct pci_dev *dev,
|
extern int pci_enable_msix(struct pci_dev *dev,
|
||||||
struct msix_entry *entries, int nvec);
|
struct msix_entry *entries, int nvec);
|
||||||
|
extern void pci_msix_shutdown(struct pci_dev *dev);
|
||||||
extern void pci_disable_msix(struct pci_dev *dev);
|
extern void pci_disable_msix(struct pci_dev *dev);
|
||||||
extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
|
extern void msi_remove_pci_irq_vectors(struct pci_dev *dev);
|
||||||
extern void pci_restore_msi_state(struct pci_dev *dev);
|
extern void pci_restore_msi_state(struct pci_dev *dev);
|
||||||
|
|
|
@ -2413,6 +2413,8 @@
|
||||||
#define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0
|
#define PCI_DEVICE_ID_INTEL_82443GX_0 0x71a0
|
||||||
#define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2
|
#define PCI_DEVICE_ID_INTEL_82443GX_2 0x71a2
|
||||||
#define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601
|
#define PCI_DEVICE_ID_INTEL_82372FB_1 0x7601
|
||||||
|
#define PCI_DEVICE_ID_INTEL_SCH_LPC 0x8119
|
||||||
|
#define PCI_DEVICE_ID_INTEL_SCH_IDE 0x811a
|
||||||
#define PCI_DEVICE_ID_INTEL_82454GX 0x84c4
|
#define PCI_DEVICE_ID_INTEL_82454GX 0x84c4
|
||||||
#define PCI_DEVICE_ID_INTEL_82450GX 0x84c5
|
#define PCI_DEVICE_ID_INTEL_82450GX 0x84c5
|
||||||
#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca
|
#define PCI_DEVICE_ID_INTEL_82451NX 0x84ca
|
||||||
|
|
Loading…
Reference in a new issue