Commit 15ea76d4 authored by Tejun Heo's avatar Tejun Heo Committed by Jesse Barnes

pccard: configure CLS on attach

For non hotplug PCI devices, the system firmware usually configures
CLS correctly.  For pccard devices system firmware can't do it and
Linux PCI layer doesn't do it either.  Unfortunately this leads to
poor performance for certain devices (sata_sil).  Unless MWI, which
requires separate configuration, is to be used, CLS doesn't affect
correctness, so the configuration should be harmless.

This patch makes pci_set_cacheline_size() always built and export it
and make pccard call it during attach.

Please note that some other PCI hotplug drivers (shpchp and pciehp)
also configure CLS on hotplug.
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Cc: Daniel Ritz <daniel.ritz@gmx.ch>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Greg KH <greg@kroah.com>
Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Cc: Axel Birndt <towerlexa@gmx.de>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 4c0eec7a
...@@ -1875,23 +1875,6 @@ void pci_clear_master(struct pci_dev *dev) ...@@ -1875,23 +1875,6 @@ void pci_clear_master(struct pci_dev *dev)
__pci_set_master(dev, false); __pci_set_master(dev, false);
} }
#ifdef PCI_DISABLE_MWI
int pci_set_mwi(struct pci_dev *dev)
{
return 0;
}
int pci_try_set_mwi(struct pci_dev *dev)
{
return 0;
}
void pci_clear_mwi(struct pci_dev *dev)
{
}
#else
/** /**
* pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed * pci_set_cacheline_size - ensure the CACHE_LINE_SIZE register is programmed
* @dev: the PCI device for which MWI is to be enabled * @dev: the PCI device for which MWI is to be enabled
...@@ -1902,13 +1885,12 @@ void pci_clear_mwi(struct pci_dev *dev) ...@@ -1902,13 +1885,12 @@ void pci_clear_mwi(struct pci_dev *dev)
* *
* RETURNS: An appropriate -ERRNO error value on error, or zero for success. * RETURNS: An appropriate -ERRNO error value on error, or zero for success.
*/ */
static int int pci_set_cacheline_size(struct pci_dev *dev)
pci_set_cacheline_size(struct pci_dev *dev)
{ {
u8 cacheline_size; u8 cacheline_size;
if (!pci_cache_line_size) if (!pci_cache_line_size)
return -EINVAL; /* The system doesn't support MWI. */ return -EINVAL;
/* Validate current setting: the PCI_CACHE_LINE_SIZE must be /* Validate current setting: the PCI_CACHE_LINE_SIZE must be
equal to or multiple of the right value. */ equal to or multiple of the right value. */
...@@ -1929,6 +1911,24 @@ pci_set_cacheline_size(struct pci_dev *dev) ...@@ -1929,6 +1911,24 @@ pci_set_cacheline_size(struct pci_dev *dev)
return -EINVAL; return -EINVAL;
} }
EXPORT_SYMBOL_GPL(pci_set_cacheline_size);
#ifdef PCI_DISABLE_MWI
int pci_set_mwi(struct pci_dev *dev)
{
return 0;
}
int pci_try_set_mwi(struct pci_dev *dev)
{
return 0;
}
void pci_clear_mwi(struct pci_dev *dev)
{
}
#else
/** /**
* pci_set_mwi - enables memory-write-invalidate PCI transaction * pci_set_mwi - enables memory-write-invalidate PCI transaction
......
...@@ -184,26 +184,33 @@ int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void ...@@ -184,26 +184,33 @@ int read_cb_mem(struct pcmcia_socket * s, int space, u_int addr, u_int len, void
=====================================================================*/ =====================================================================*/
/* static void cardbus_config_irq_and_cls(struct pci_bus *bus, int irq)
* Since there is only one interrupt available to CardBus
* devices, all devices downstream of this device must
* be using this IRQ.
*/
static void cardbus_assign_irqs(struct pci_bus *bus, int irq)
{ {
struct pci_dev *dev; struct pci_dev *dev;
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
u8 irq_pin; u8 irq_pin;
/*
* Since there is only one interrupt available to
* CardBus devices, all devices downstream of this
* device must be using this IRQ.
*/
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin); pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
if (irq_pin) { if (irq_pin) {
dev->irq = irq; dev->irq = irq;
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
} }
/*
* Some controllers transfer very slowly with 0 CLS.
* Configure it. This may fail as CLS configuration
* is mandatory only for MWI.
*/
pci_set_cacheline_size(dev);
if (dev->subordinate) if (dev->subordinate)
cardbus_assign_irqs(dev->subordinate, irq); cardbus_config_irq_and_cls(dev->subordinate, irq);
} }
} }
...@@ -228,7 +235,7 @@ int __ref cb_alloc(struct pcmcia_socket * s) ...@@ -228,7 +235,7 @@ int __ref cb_alloc(struct pcmcia_socket * s)
*/ */
pci_bus_size_bridges(bus); pci_bus_size_bridges(bus);
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
cardbus_assign_irqs(bus, s->pci_irq); cardbus_config_irq_and_cls(bus, s->pci_irq);
/* socket specific tune function */ /* socket specific tune function */
if (s->tune_bridge) if (s->tune_bridge)
......
...@@ -701,6 +701,7 @@ void pci_disable_device(struct pci_dev *dev); ...@@ -701,6 +701,7 @@ void pci_disable_device(struct pci_dev *dev);
void pci_set_master(struct pci_dev *dev); void pci_set_master(struct pci_dev *dev);
void pci_clear_master(struct pci_dev *dev); void pci_clear_master(struct pci_dev *dev);
int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state); int pci_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state state);
int pci_set_cacheline_size(struct pci_dev *dev);
#define HAVE_PCI_SET_MWI #define HAVE_PCI_SET_MWI
int __must_check pci_set_mwi(struct pci_dev *dev); int __must_check pci_set_mwi(struct pci_dev *dev);
int pci_try_set_mwi(struct pci_dev *dev); int pci_try_set_mwi(struct pci_dev *dev);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment