Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7efe5d7c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/pci-2.6

parents dbe0580d f8977d0a
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -286,7 +286,9 @@ X!Edrivers/pci/search.c
 -->
!Edrivers/pci/msi.c
!Edrivers/pci/bus.c
!Edrivers/pci/hotplug.c
<!-- FIXME: Removed for now since no structured comments in source
X!Edrivers/pci/hotplug.c
-->
!Edrivers/pci/probe.c
!Edrivers/pci/rom.c
     </sect1>
+59 −0
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@
 * Exceptions for specific devices. Usually work-arounds for fatal design flaws.
 */

#include <linux/delay.h>
#include <linux/dmi.h>
#include <linux/pci.h>
#include <linux/init.h>
#include "pci.h"
@@ -384,3 +386,60 @@ static void __devinit pci_fixup_video(struct pci_dev *pdev)
	}
}
DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_video);

/*
 * Some Toshiba laptops need extra code to enable their TI TSB43AB22/A.
 *
 * We pretend to bring them out of full D3 state, and restore the proper
 * IRQ, PCI cache line size, and BARs, otherwise the device won't function
 * properly.  In some cases, the device will generate an interrupt on
 * the wrong IRQ line, causing any devices sharing the the line it's
 * *supposed* to use to be disabled by the kernel's IRQ debug code.
 */
static u16 toshiba_line_size;

static struct dmi_system_id __devinit toshiba_ohci1394_dmi_table[] = {
	{
		.ident = "Toshiba PS5 based laptop",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
			DMI_MATCH(DMI_PRODUCT_VERSION, "PS5"),
		},
	},
	{
		.ident = "Toshiba PSM4 based laptop",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
			DMI_MATCH(DMI_PRODUCT_VERSION, "PSM4"),
		},
	},
	{ }
};

static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev)
{
	if (!dmi_check_system(toshiba_ohci1394_dmi_table))
		return; /* only applies to certain Toshibas (so far) */

	dev->current_state = PCI_D3cold;
	pci_read_config_word(dev, PCI_CACHE_LINE_SIZE, &toshiba_line_size);
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TI, 0x8032,
			 pci_pre_fixup_toshiba_ohci1394);

static void __devinit pci_post_fixup_toshiba_ohci1394(struct pci_dev *dev)
{
	if (!dmi_check_system(toshiba_ohci1394_dmi_table))
		return; /* only applies to certain Toshibas (so far) */

	/* Restore config space on Toshiba laptops */
	mdelay(10);
	pci_write_config_word(dev, PCI_CACHE_LINE_SIZE, toshiba_line_size);
	pci_write_config_word(dev, PCI_INTERRUPT_LINE, dev->irq);
	pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
			       pci_resource_start(dev, 0));
	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
			       pci_resource_start(dev, 1));
}
DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_TI, 0x8032,
			 pci_post_fixup_toshiba_ohci1394);
+89 −0
Original line number Diff line number Diff line
@@ -60,3 +60,92 @@ EXPORT_SYMBOL(pci_bus_read_config_dword);
EXPORT_SYMBOL(pci_bus_write_config_byte);
EXPORT_SYMBOL(pci_bus_write_config_word);
EXPORT_SYMBOL(pci_bus_write_config_dword);

static u32 pci_user_cached_config(struct pci_dev *dev, int pos)
{
	u32 data;

	data = dev->saved_config_space[pos/sizeof(dev->saved_config_space[0])];
	data >>= (pos % sizeof(dev->saved_config_space[0])) * 8;
	return data;
}

#define PCI_USER_READ_CONFIG(size,type)					\
int pci_user_read_config_##size						\
	(struct pci_dev *dev, int pos, type *val)			\
{									\
	unsigned long flags;						\
	int ret = 0;							\
	u32 data = -1;							\
	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
	spin_lock_irqsave(&pci_lock, flags);				\
	if (likely(!dev->block_ucfg_access))				\
		ret = dev->bus->ops->read(dev->bus, dev->devfn,		\
					pos, sizeof(type), &data);	\
	else if (pos < sizeof(dev->saved_config_space))			\
		data = pci_user_cached_config(dev, pos); 		\
	spin_unlock_irqrestore(&pci_lock, flags);			\
	*val = (type)data;						\
	return ret;							\
}

#define PCI_USER_WRITE_CONFIG(size,type)				\
int pci_user_write_config_##size					\
	(struct pci_dev *dev, int pos, type val)			\
{									\
	unsigned long flags;						\
	int ret = -EIO;							\
	if (PCI_##size##_BAD) return PCIBIOS_BAD_REGISTER_NUMBER;	\
	spin_lock_irqsave(&pci_lock, flags);				\
	if (likely(!dev->block_ucfg_access))				\
		ret = dev->bus->ops->write(dev->bus, dev->devfn,	\
					pos, sizeof(type), val);	\
	spin_unlock_irqrestore(&pci_lock, flags);			\
	return ret;							\
}

PCI_USER_READ_CONFIG(byte, u8)
PCI_USER_READ_CONFIG(word, u16)
PCI_USER_READ_CONFIG(dword, u32)
PCI_USER_WRITE_CONFIG(byte, u8)
PCI_USER_WRITE_CONFIG(word, u16)
PCI_USER_WRITE_CONFIG(dword, u32)

/**
 * pci_block_user_cfg_access - Block userspace PCI config reads/writes
 * @dev:	pci device struct
 *
 * This function blocks any userspace PCI config accesses from occurring.
 * When blocked, any writes will be bit bucketed and reads will return the
 * data saved using pci_save_state for the first 64 bytes of config
 * space and return 0xff for all other config reads.
 **/
void pci_block_user_cfg_access(struct pci_dev *dev)
{
	unsigned long flags;

	pci_save_state(dev);

	/* spinlock to synchronize with anyone reading config space now */
	spin_lock_irqsave(&pci_lock, flags);
	dev->block_ucfg_access = 1;
	spin_unlock_irqrestore(&pci_lock, flags);
}
EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);

/**
 * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
 * @dev:	pci device struct
 *
 * This function allows userspace PCI config accesses to resume.
 **/
void pci_unblock_user_cfg_access(struct pci_dev *dev)
{
	unsigned long flags;

	/* spinlock to synchronize with anyone reading saved config space */
	spin_lock_irqsave(&pci_lock, flags);
	dev->block_ucfg_access = 0;
	spin_unlock_irqrestore(&pci_lock, flags);
}
EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
+8 −0
Original line number Diff line number Diff line
@@ -58,6 +58,9 @@ static LIST_HEAD(bridge_list);

static void handle_hotplug_event_bridge (acpi_handle, u32, void *);
static void handle_hotplug_event_func (acpi_handle, u32, void *);
static void acpiphp_sanitize_bus(struct pci_bus *bus);
static void acpiphp_set_hpp_values(acpi_handle handle, struct pci_bus *bus);


/*
 * initialization & terminatation routines
@@ -796,8 +799,13 @@ static int enable_device(struct acpiphp_slot *slot)
		}
	}

	pci_bus_size_bridges(bus);
	pci_bus_assign_resources(bus);
	acpiphp_sanitize_bus(bus);
	pci_enable_bridges(bus);
	pci_bus_add_devices(bus);
	acpiphp_set_hpp_values(DEVICE_ACPI_HANDLE(&bus->self->dev), bus);
	acpiphp_configure_ioapics(DEVICE_ACPI_HANDLE(&bus->self->dev));

	/* associate pci_dev to our representation */
	list_for_each (l, &slot->funcs) {
+21 −4
Original line number Diff line number Diff line
@@ -78,11 +78,20 @@ static void __iomem *csr_int_mask;

static int zt5550_hc_config(struct pci_dev *pdev)
{
	int ret;

	/* Since we know that no boards exist with two HC chips, treat it as an error */
	if(hc_dev) {
		err("too many host controller devices?");
		return -EBUSY;
	}

	ret = pci_enable_device(pdev);
	if(ret) {
		err("cannot enable %s\n", pci_name(pdev));
		return ret;
	}

	hc_dev = pdev;
	dbg("hc_dev = %p", hc_dev);
	dbg("pci resource start %lx", pci_resource_start(hc_dev, 1));
@@ -91,7 +100,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
	if(!request_mem_region(pci_resource_start(hc_dev, 1),
				pci_resource_len(hc_dev, 1), MY_NAME)) {
		err("cannot reserve MMIO region");
		return -ENOMEM;
		ret = -ENOMEM;
		goto exit_disable_device;
	}

	hc_registers =
@@ -99,9 +109,8 @@ static int zt5550_hc_config(struct pci_dev *pdev)
	if(!hc_registers) {
		err("cannot remap MMIO region %lx @ %lx",
		    pci_resource_len(hc_dev, 1), pci_resource_start(hc_dev, 1));
		release_mem_region(pci_resource_start(hc_dev, 1),
				   pci_resource_len(hc_dev, 1));
		return -ENODEV;
		ret = -ENODEV;
		goto exit_release_region;
	}

	csr_hc_index = hc_registers + CSR_HCINDEX;
@@ -124,6 +133,13 @@ static int zt5550_hc_config(struct pci_dev *pdev)
	writeb((u8) ALL_DIRECT_INTS_MASK, csr_int_mask);
	dbg("disabled timer0, timer1 and ENUM interrupts");
	return 0;

exit_release_region:
	release_mem_region(pci_resource_start(hc_dev, 1),
			   pci_resource_len(hc_dev, 1));
exit_disable_device:
	pci_disable_device(hc_dev);
	return ret;
}

static int zt5550_hc_cleanup(void)
@@ -134,6 +150,7 @@ static int zt5550_hc_cleanup(void)
	iounmap(hc_registers);
	release_mem_region(pci_resource_start(hc_dev, 1),
			   pci_resource_len(hc_dev, 1));
	pci_disable_device(hc_dev);
	return 0;
}

Loading