summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@pobox.com>2005-11-11 13:50:22 +0300
committerJeff Garzik <jgarzik@pobox.com>2005-11-11 13:50:22 +0300
commitf85272a97825d4a67098a8ad70fa5efb55e4847a (patch)
treee55b38e21b45213269057417032db4440e8f5eed /drivers
parent1c72d8d90da3b29540c3c281a3e0b743ee6b6f74 (diff)
parent5e04e7fe774794b837e1d3897e6b96ae2d06679a (diff)
downloadlinux-f85272a97825d4a67098a8ad70fa5efb55e4847a.tar.xz
Merge branch 'master'
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/glue.c1
-rw-r--r--drivers/atm/horizon.c4
-rw-r--r--drivers/char/agp/ali-agp.c1
-rw-r--r--drivers/char/agp/amd-k7-agp.c1
-rw-r--r--drivers/char/agp/amd64-agp.c1
-rw-r--r--drivers/char/agp/ati-agp.c1
-rw-r--r--drivers/char/agp/efficeon-agp.c1
-rw-r--r--drivers/char/agp/i460-agp.c1
-rw-r--r--drivers/char/agp/intel-agp.c1
-rw-r--r--drivers/char/agp/nvidia-agp.c1
-rw-r--r--drivers/char/agp/sis-agp.c1
-rw-r--r--drivers/char/agp/sworks-agp.c1
-rw-r--r--drivers/char/agp/uninorth-agp.c1
-rw-r--r--drivers/char/agp/via-agp.c1
-rw-r--r--drivers/char/epca.c1
-rw-r--r--drivers/char/synclink.c1
-rw-r--r--drivers/char/synclinkmp.c1
-rw-r--r--drivers/char/watchdog/pcwd_pci.c1
-rw-r--r--drivers/char/watchdog/wdt_pci.c1
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c1
-rw-r--r--drivers/i2c/busses/i2c-ali1563.c1
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c1
-rw-r--r--drivers/i2c/busses/i2c-amd756.c1
-rw-r--r--drivers/i2c/busses/i2c-amd8111.c1
-rw-r--r--drivers/i2c/busses/i2c-hydra.c1
-rw-r--r--drivers/i2c/busses/i2c-i801.c1
-rw-r--r--drivers/i2c/busses/i2c-i810.c1
-rw-r--r--drivers/i2c/busses/i2c-nforce2.c1
-rw-r--r--drivers/i2c/busses/i2c-piix4.c1
-rw-r--r--drivers/i2c/busses/i2c-prosavage.c1
-rw-r--r--drivers/i2c/busses/i2c-savage4.c1
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c1
-rw-r--r--drivers/i2c/busses/i2c-sis630.c1
-rw-r--r--drivers/i2c/busses/i2c-sis96x.c1
-rw-r--r--drivers/i2c/busses/i2c-via.c1
-rw-r--r--drivers/i2c/busses/i2c-viapro.c1
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c1
-rw-r--r--drivers/ide/setup-pci.c12
-rw-r--r--drivers/infiniband/core/user_mad.c129
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c12
-rw-r--r--drivers/infiniband/core/verbs.c12
-rw-r--r--drivers/infiniband/hw/mthca/mthca_catas.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cmd.c2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_cq.c16
-rw-r--r--drivers/infiniband/hw/mthca/mthca_dev.h2
-rw-r--r--drivers/infiniband/hw/mthca/mthca_main.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.c3
-rw-r--r--drivers/infiniband/hw/mthca/mthca_provider.h1
-rw-r--r--drivers/infiniband/hw/mthca/mthca_qp.c113
-rw-r--r--drivers/infiniband/hw/mthca/mthca_srq.c22
-rw-r--r--drivers/infiniband/hw/mthca/mthca_wqe.h3
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h15
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_fs.c177
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c72
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_multicast.c26
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_vlan.c7
-rw-r--r--drivers/net/bnx2.c16
-rw-r--r--drivers/net/fs_enet/fs_enet-main.c1
-rw-r--r--drivers/net/fs_enet/mac-fcc.c1
-rw-r--r--drivers/net/fs_enet/mac-fec.c1
-rw-r--r--drivers/net/fs_enet/mac-scc.c1
-rw-r--r--drivers/net/spider_net.c1
-rw-r--r--drivers/pci/access.c2
-rw-r--r--drivers/pci/hotplug/pciehp.h135
-rw-r--r--drivers/pci/hotplug/pciehp_core.c108
-rw-r--r--drivers/pci/hotplug/pciehp_ctrl.c1979
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c113
-rw-r--r--drivers/pci/hotplug/pciehp_pci.c840
-rw-r--r--drivers/pci/hotplug/pciehprm.h52
-rw-r--r--drivers/pci/hotplug/pciehprm_acpi.c1727
-rw-r--r--drivers/pci/hotplug/pciehprm_nonacpi.c464
-rw-r--r--drivers/pci/hotplug/pciehprm_nonacpi.h56
-rw-r--r--drivers/pci/hotplug/rpadlpar_core.c81
-rw-r--r--drivers/pci/hotplug/rpaphp.h2
-rw-r--r--drivers/pci/hotplug/rpaphp_pci.c76
-rw-r--r--drivers/pci/hotplug/shpchp_pci.c2
-rw-r--r--drivers/pci/msi.c20
-rw-r--r--drivers/pci/pci-acpi.c11
-rw-r--r--drivers/pci/pci-driver.c11
-rw-r--r--drivers/pci/pci.c46
-rw-r--r--drivers/pci/quirks.c19
-rw-r--r--drivers/pcmcia/Kconfig2
-rw-r--r--drivers/pcmcia/Makefile6
-rw-r--r--drivers/pcmcia/au1000_db1x00.c1
-rw-r--r--drivers/pcmcia/au1000_generic.h2
-rw-r--r--drivers/pcmcia/au1000_pb1x00.c1
-rw-r--r--drivers/pcmcia/au1000_xxs1500.c1
-rw-r--r--drivers/pcmcia/i82365.c1
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c24
-rw-r--r--drivers/sbus/char/display7seg.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c1
-rw-r--r--drivers/usb/gadget/goku_udc.c1
-rw-r--r--drivers/usb/gadget/net2280.c1
-rw-r--r--drivers/usb/host/ehci-pci.c1
-rw-r--r--drivers/usb/host/ohci-pci.c1
-rw-r--r--drivers/usb/host/uhci-hcd.c1
-rw-r--r--drivers/video/backlight/corgi_bl.c6
97 files changed, 995 insertions, 5491 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 3937adf4e5e5..aa993715d644 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -203,6 +203,7 @@ acpi_handle acpi_get_pci_rootbridge_handle(unsigned int seg, unsigned int bus)
acpi_get_devices(PCI_ROOT_HID_STRING, find_pci_rootbridge, &find, NULL);
return find.handle;
}
+EXPORT_SYMBOL_GPL(acpi_get_pci_rootbridge_handle);
/* Get device's handler per its address under its parent */
struct acpi_find_child {
diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c
index 0cded0468003..821c81e8cd38 100644
--- a/drivers/atm/horizon.c
+++ b/drivers/atm/horizon.c
@@ -1511,8 +1511,8 @@ static inline short setup_idle_tx_channel (hrz_dev * dev, hrz_vcc * vcc) {
// a.k.a. prepare the channel and remember that we have done so.
tx_ch_desc * tx_desc = &memmap->tx_descs[tx_channel];
- u16 rd_ptr;
- u16 wr_ptr;
+ u32 rd_ptr;
+ u32 wr_ptr;
u16 channel = vcc->channel;
unsigned long flags;
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c
index ba54b5872578..b02fc2267159 100644
--- a/drivers/char/agp/ali-agp.c
+++ b/drivers/char/agp/ali-agp.c
@@ -389,7 +389,6 @@ static struct pci_device_id agp_ali_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_ali_pci_table);
static struct pci_driver agp_ali_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-ali",
.id_table = agp_ali_pci_table,
.probe = agp_ali_probe,
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c
index 40fcd88b2cea..1f776651ac64 100644
--- a/drivers/char/agp/amd-k7-agp.c
+++ b/drivers/char/agp/amd-k7-agp.c
@@ -515,7 +515,6 @@ static struct pci_device_id agp_amdk7_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_amdk7_pci_table);
static struct pci_driver agp_amdk7_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-amdk7",
.id_table = agp_amdk7_pci_table,
.probe = agp_amdk7_probe,
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 8f748fddca94..78ce98a69f37 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -703,7 +703,6 @@ static struct pci_device_id agp_amd64_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_amd64_pci_table);
static struct pci_driver agp_amd64_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-amd64",
.id_table = agp_amd64_pci_table,
.probe = agp_amd64_probe,
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c
index fbd415565463..53372a83b675 100644
--- a/drivers/char/agp/ati-agp.c
+++ b/drivers/char/agp/ati-agp.c
@@ -521,7 +521,6 @@ static struct pci_device_id agp_ati_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_ati_pci_table);
static struct pci_driver agp_ati_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-ati",
.id_table = agp_ati_pci_table,
.probe = agp_ati_probe,
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c
index d41e0a62e32e..e7aea77a60f9 100644
--- a/drivers/char/agp/efficeon-agp.c
+++ b/drivers/char/agp/efficeon-agp.c
@@ -429,7 +429,6 @@ static struct pci_device_id agp_efficeon_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table);
static struct pci_driver agp_efficeon_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-efficeon",
.id_table = agp_efficeon_pci_table,
.probe = agp_efficeon_probe,
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c
index 34a444658ffe..8ee19a4a6bce 100644
--- a/drivers/char/agp/i460-agp.c
+++ b/drivers/char/agp/i460-agp.c
@@ -622,7 +622,6 @@ static struct pci_device_id agp_intel_i460_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_intel_i460_pci_table);
static struct pci_driver agp_intel_i460_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-intel-i460",
.id_table = agp_intel_i460_pci_table,
.probe = agp_intel_i460_probe,
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 027161ab88e9..e7bed5047dcc 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -1827,7 +1827,6 @@ static struct pci_device_id agp_intel_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_intel_pci_table);
static struct pci_driver agp_intel_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-intel",
.id_table = agp_intel_pci_table,
.probe = agp_intel_probe,
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c
index 3aed0c5e2f92..80dafa3030bd 100644
--- a/drivers/char/agp/nvidia-agp.c
+++ b/drivers/char/agp/nvidia-agp.c
@@ -398,7 +398,6 @@ static struct pci_device_id agp_nvidia_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_nvidia_pci_table);
static struct pci_driver agp_nvidia_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-nvidia",
.id_table = agp_nvidia_pci_table,
.probe = agp_nvidia_probe,
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c
index a701361a8890..ebc05554045c 100644
--- a/drivers/char/agp/sis-agp.c
+++ b/drivers/char/agp/sis-agp.c
@@ -332,7 +332,6 @@ static struct pci_device_id agp_sis_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_sis_pci_table);
static struct pci_driver agp_sis_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-sis",
.id_table = agp_sis_pci_table,
.probe = agp_sis_probe,
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c
index 5a5392dd1254..3f8f7fa6b0ff 100644
--- a/drivers/char/agp/sworks-agp.c
+++ b/drivers/char/agp/sworks-agp.c
@@ -545,7 +545,6 @@ static struct pci_device_id agp_serverworks_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_serverworks_pci_table);
static struct pci_driver agp_serverworks_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-serverworks",
.id_table = agp_serverworks_pci_table,
.probe = agp_serverworks_probe,
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c
index 183c50acab27..c8255312b8c1 100644
--- a/drivers/char/agp/uninorth-agp.c
+++ b/drivers/char/agp/uninorth-agp.c
@@ -658,7 +658,6 @@ static struct pci_device_id agp_uninorth_pci_table[] = {
MODULE_DEVICE_TABLE(pci, agp_uninorth_pci_table);
static struct pci_driver agp_uninorth_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-uninorth",
.id_table = agp_uninorth_pci_table,
.probe = agp_uninorth_probe,
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c
index 5d9a13700074..c847df575cf5 100644
--- a/drivers/char/agp/via-agp.c
+++ b/drivers/char/agp/via-agp.c
@@ -518,7 +518,6 @@ MODULE_DEVICE_TABLE(pci, agp_via_pci_table);
static struct pci_driver agp_via_pci_driver = {
- .owner = THIS_MODULE,
.name = "agpgart-via",
.id_table = agp_via_pci_table,
.probe = agp_via_probe,
diff --git a/drivers/char/epca.c b/drivers/char/epca.c
index b7a0e4d6b934..407708a001e4 100644
--- a/drivers/char/epca.c
+++ b/drivers/char/epca.c
@@ -3113,7 +3113,6 @@ MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
int __init init_PCI (void)
{ /* Begin init_PCI */
memset (&epca_driver, 0, sizeof (epca_driver));
- epca_driver.owner = THIS_MODULE;
epca_driver.name = "epca";
epca_driver.id_table = epca_pci_tbl;
epca_driver.probe = epca_init_one;
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 5d1ffa3bd4c3..82c6abde68df 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -912,7 +912,6 @@ MODULE_DEVICE_TABLE(pci, synclink_pci_tbl);
MODULE_LICENSE("GPL");
static struct pci_driver synclink_pci_driver = {
- .owner = THIS_MODULE,
.name = "synclink",
.id_table = synclink_pci_tbl,
.probe = synclink_init_one,
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 7c063c5abc55..ee5a40be9f99 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -500,7 +500,6 @@ MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl);
MODULE_LICENSE("GPL");
static struct pci_driver synclinkmp_pci_driver = {
- .owner = THIS_MODULE,
.name = "synclinkmp",
.id_table = synclinkmp_pci_tbl,
.probe = synclinkmp_init_one,
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index d9ef55bdf88a..2451edbefece 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -755,7 +755,6 @@ static struct pci_device_id pcipcwd_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl);
static struct pci_driver pcipcwd_driver = {
- .owner = THIS_MODULE,
.name = WATCHDOG_NAME,
.id_table = pcipcwd_pci_tbl,
.probe = pcipcwd_card_init,
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
index dc9370f6c348..4b3311993d48 100644
--- a/drivers/char/watchdog/wdt_pci.c
+++ b/drivers/char/watchdog/wdt_pci.c
@@ -711,7 +711,6 @@ MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
static struct pci_driver wdtpci_driver = {
- .owner = THIS_MODULE,
.name = "wdt_pci",
.id_table = wdtpci_pci_tbl,
.probe = wdtpci_init_one,
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index ba90f5140af6..3eb47890db40 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -513,7 +513,6 @@ static void __devexit ali1535_remove(struct pci_dev *dev)
}
static struct pci_driver ali1535_driver = {
- .owner = THIS_MODULE,
.name = "ali1535_smbus",
.id_table = ali1535_ids,
.probe = ali1535_probe,
diff --git a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
index f1a62d892425..e6f63208fc4a 100644
--- a/drivers/i2c/busses/i2c-ali1563.c
+++ b/drivers/i2c/busses/i2c-ali1563.c
@@ -408,7 +408,6 @@ static struct pci_device_id __devinitdata ali1563_id_table[] = {
MODULE_DEVICE_TABLE (pci, ali1563_id_table);
static struct pci_driver ali1563_pci_driver = {
- .owner = THIS_MODULE,
.name = "ali1563_smbus",
.id_table = ali1563_id_table,
.probe = ali1563_probe,
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index 400b08ed4299..7a5c0941dbc1 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -504,7 +504,6 @@ static void __devexit ali15x3_remove(struct pci_dev *dev)
}
static struct pci_driver ali15x3_driver = {
- .owner = THIS_MODULE,
.name = "ali15x3_smbus",
.id_table = ali15x3_ids,
.probe = ali15x3_probe,
diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
index de035d137c3f..1750dedaf4b5 100644
--- a/drivers/i2c/busses/i2c-amd756.c
+++ b/drivers/i2c/busses/i2c-amd756.c
@@ -401,7 +401,6 @@ static void __devexit amd756_remove(struct pci_dev *dev)
}
static struct pci_driver amd756_driver = {
- .owner = THIS_MODULE,
.name = "amd756_smbus",
.id_table = amd756_ids,
.probe = amd756_probe,
diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
index f3b79a68dbec..e5ef560e686a 100644
--- a/drivers/i2c/busses/i2c-amd8111.c
+++ b/drivers/i2c/busses/i2c-amd8111.c
@@ -384,7 +384,6 @@ static void __devexit amd8111_remove(struct pci_dev *dev)
}
static struct pci_driver amd8111_driver = {
- .owner = THIS_MODULE,
.name = "amd8111_smbus2",
.id_table = amd8111_ids,
.probe = amd8111_probe,
diff --git a/drivers/i2c/busses/i2c-hydra.c b/drivers/i2c/busses/i2c-hydra.c
index 1b5354e24bf5..e0cb3b0f92fa 100644
--- a/drivers/i2c/busses/i2c-hydra.c
+++ b/drivers/i2c/busses/i2c-hydra.c
@@ -155,7 +155,6 @@ static void __devexit hydra_remove(struct pci_dev *dev)
static struct pci_driver hydra_driver = {
- .owner = THIS_MODULE,
.name = "hydra_smbus",
.id_table = hydra_ids,
.probe = hydra_probe,
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 4f63195069da..ac3eafa8aac0 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -560,7 +560,6 @@ static void __devexit i801_remove(struct pci_dev *dev)
}
static struct pci_driver i801_driver = {
- .owner = THIS_MODULE,
.name = "i801_smbus",
.id_table = i801_ids,
.probe = i801_probe,
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
index 52bc30593bd7..748be30f2bae 100644
--- a/drivers/i2c/busses/i2c-i810.c
+++ b/drivers/i2c/busses/i2c-i810.c
@@ -233,7 +233,6 @@ static void __devexit i810_remove(struct pci_dev *dev)
}
static struct pci_driver i810_driver = {
- .owner = THIS_MODULE,
.name = "i810_smbus",
.id_table = i810_ids,
.probe = i810_probe,
diff --git a/drivers/i2c/busses/i2c-nforce2.c b/drivers/i2c/busses/i2c-nforce2.c
index fd26036e68a3..4d18e6e5f159 100644
--- a/drivers/i2c/busses/i2c-nforce2.c
+++ b/drivers/i2c/busses/i2c-nforce2.c
@@ -347,7 +347,6 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
}
static struct pci_driver nforce2_driver = {
- .owner = THIS_MODULE,
.name = "nForce2_smbus",
.id_table = nforce2_ids,
.probe = nforce2_probe,
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 7d63eec423fe..692f47345481 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -462,7 +462,6 @@ static void __devexit piix4_remove(struct pci_dev *dev)
}
static struct pci_driver piix4_driver = {
- .owner = THIS_MODULE,
.name = "piix4_smbus",
.id_table = piix4_ids,
.probe = piix4_probe,
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
index 42cb1d8ca659..9479525892e3 100644
--- a/drivers/i2c/busses/i2c-prosavage.c
+++ b/drivers/i2c/busses/i2c-prosavage.c
@@ -301,7 +301,6 @@ static struct pci_device_id prosavage_pci_tbl[] = {
MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
static struct pci_driver prosavage_driver = {
- .owner = THIS_MODULE,
.name = "prosavage_smbus",
.id_table = prosavage_pci_tbl,
.probe = prosavage_probe,
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
index aebe87ba4033..0c8518298e4d 100644
--- a/drivers/i2c/busses/i2c-savage4.c
+++ b/drivers/i2c/busses/i2c-savage4.c
@@ -179,7 +179,6 @@ static void __devexit savage4_remove(struct pci_dev *dev)
}
static struct pci_driver savage4_driver = {
- .owner = THIS_MODULE,
.name = "savage4_smbus",
.id_table = savage4_ids,
.probe = savage4_probe,
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 3ad27c3ba15b..b57ab74d23ec 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -398,7 +398,6 @@ static void __devexit sis5595_remove(struct pci_dev *dev)
}
static struct pci_driver sis5595_driver = {
- .owner = THIS_MODULE,
.name = "sis5595_smbus",
.id_table = sis5595_ids,
.probe = sis5595_probe,
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 7f49e5fd3ff0..acb75e282414 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -496,7 +496,6 @@ static void __devexit sis630_remove(struct pci_dev *dev)
static struct pci_driver sis630_driver = {
- .owner = THIS_MODULE,
.name = "sis630_smbus",
.id_table = sis630_ids,
.probe = sis630_probe,
diff --git a/drivers/i2c/busses/i2c-sis96x.c b/drivers/i2c/busses/i2c-sis96x.c
index 6a134c091324..3024907cdafe 100644
--- a/drivers/i2c/busses/i2c-sis96x.c
+++ b/drivers/i2c/busses/i2c-sis96x.c
@@ -329,7 +329,6 @@ static void __devexit sis96x_remove(struct pci_dev *dev)
}
static struct pci_driver sis96x_driver = {
- .owner = THIS_MODULE,
.name = "sis96x_smbus",
.id_table = sis96x_ids,
.probe = sis96x_probe,
diff --git a/drivers/i2c/busses/i2c-via.c b/drivers/i2c/busses/i2c-via.c
index 544a38e64394..484bbacfce6b 100644
--- a/drivers/i2c/busses/i2c-via.c
+++ b/drivers/i2c/busses/i2c-via.c
@@ -159,7 +159,6 @@ static void __devexit vt586b_remove(struct pci_dev *dev)
static struct pci_driver vt586b_driver = {
- .owner = THIS_MODULE,
.name = "vt586b_smbus",
.id_table = vt586b_ids,
.probe = vt586b_probe,
diff --git a/drivers/i2c/busses/i2c-viapro.c b/drivers/i2c/busses/i2c-viapro.c
index a2237d4b2cf2..47e52bf2c5ec 100644
--- a/drivers/i2c/busses/i2c-viapro.c
+++ b/drivers/i2c/busses/i2c-viapro.c
@@ -440,7 +440,6 @@ static struct pci_device_id vt596_ids[] = {
MODULE_DEVICE_TABLE(pci, vt596_ids);
static struct pci_driver vt596_driver = {
- .owner = THIS_MODULE,
.name = "vt596_smbus",
.id_table = vt596_ids,
.probe = vt596_probe,
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
index 650c3ebde84c..b675773b0cc1 100644
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ b/drivers/i2c/busses/i2c-voodoo3.c
@@ -225,7 +225,6 @@ static void __devexit voodoo3_remove(struct pci_dev *dev)
}
static struct pci_driver voodoo3_driver = {
- .owner = THIS_MODULE,
.name = "voodoo3_smbus",
.id_table = voodoo3_ids,
.probe = voodoo3_probe,
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c
index 18ed7765417c..d4f2111d4364 100644
--- a/drivers/ide/setup-pci.c
+++ b/drivers/ide/setup-pci.c
@@ -787,8 +787,9 @@ static int pre_init = 1; /* Before first ordered IDE scan */
static LIST_HEAD(ide_pci_drivers);
/*
- * ide_register_pci_driver - attach IDE driver
+ * __ide_register_pci_driver - attach IDE driver
* @driver: pci driver
+ * @module: owner module of the driver
*
* Registers a driver with the IDE layer. The IDE layer arranges that
* boot time setup is done in the expected device order and then
@@ -801,15 +802,16 @@ static LIST_HEAD(ide_pci_drivers);
* Returns are the same as for pci_register_driver
*/
-int ide_pci_register_driver(struct pci_driver *driver)
+int __ide_pci_register_driver(struct pci_driver *driver, struct module *module)
{
if(!pre_init)
- return pci_module_init(driver);
+ return __pci_register_driver(driver, module);
+ driver->driver.owner = module;
list_add_tail(&driver->node, &ide_pci_drivers);
return 0;
}
-EXPORT_SYMBOL_GPL(ide_pci_register_driver);
+EXPORT_SYMBOL_GPL(__ide_pci_register_driver);
/**
* ide_unregister_pci_driver - unregister an IDE driver
@@ -897,6 +899,6 @@ void __init ide_scan_pcibus (int scan_direction)
{
list_del(l);
d = list_entry(l, struct pci_driver, node);
- pci_register_driver(d);
+ __pci_register_driver(d, d->driver.owner);
}
}
diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c
index aed5ca23fb22..5ea741f47fc8 100644
--- a/drivers/infiniband/core/user_mad.c
+++ b/drivers/infiniband/core/user_mad.c
@@ -31,7 +31,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
- * $Id: user_mad.c 2814 2005-07-06 19:14:09Z halr $
+ * $Id: user_mad.c 4010 2005-11-09 23:11:56Z roland $
*/
#include <linux/module.h>
@@ -110,13 +110,13 @@ struct ib_umad_device {
};
struct ib_umad_file {
- struct ib_umad_port *port;
- struct list_head recv_list;
- struct list_head port_list;
- spinlock_t recv_lock;
- wait_queue_head_t recv_wait;
- struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS];
- struct ib_mr *mr[IB_UMAD_MAX_AGENTS];
+ struct ib_umad_port *port;
+ struct list_head recv_list;
+ struct list_head port_list;
+ spinlock_t recv_lock;
+ wait_queue_head_t recv_wait;
+ struct ib_mad_agent *agent[IB_UMAD_MAX_AGENTS];
+ int agents_dead;
};
struct ib_umad_packet {
@@ -145,6 +145,12 @@ static void ib_umad_release_dev(struct kref *ref)
kfree(dev);
}
+/* caller must hold port->mutex at least for reading */
+static struct ib_mad_agent *__get_agent(struct ib_umad_file *file, int id)
+{
+ return file->agents_dead ? NULL : file->agent[id];
+}
+
static int queue_packet(struct ib_umad_file *file,
struct ib_mad_agent *agent,
struct ib_umad_packet *packet)
@@ -152,10 +158,11 @@ static int queue_packet(struct ib_umad_file *file,
int ret = 1;
down_read(&file->port->mutex);
+
for (packet->mad.hdr.id = 0;
packet->mad.hdr.id < IB_UMAD_MAX_AGENTS;
packet->mad.hdr.id++)
- if (agent == file->agent[packet->mad.hdr.id]) {
+ if (agent == __get_agent(file, packet->mad.hdr.id)) {
spin_lock_irq(&file->recv_lock);
list_add_tail(&packet->list, &file->recv_list);
spin_unlock_irq(&file->recv_lock);
@@ -327,7 +334,7 @@ static ssize_t ib_umad_write(struct file *filp, const char __user *buf,
down_read(&file->port->mutex);
- agent = file->agent[packet->mad.hdr.id];
+ agent = __get_agent(file, packet->mad.hdr.id);
if (!agent) {
ret = -EINVAL;
goto err_up;
@@ -481,7 +488,7 @@ static int ib_umad_reg_agent(struct ib_umad_file *file, unsigned long arg)
}
for (agent_id = 0; agent_id < IB_UMAD_MAX_AGENTS; ++agent_id)
- if (!file->agent[agent_id])
+ if (!__get_agent(file, agent_id))
goto found;
ret = -ENOMEM;
@@ -505,29 +512,15 @@ found:
goto out;
}
- file->agent[agent_id] = agent;
-
- file->mr[agent_id] = ib_get_dma_mr(agent->qp->pd, IB_ACCESS_LOCAL_WRITE);
- if (IS_ERR(file->mr[agent_id])) {
- ret = -ENOMEM;
- goto err;
- }
-
if (put_user(agent_id,
(u32 __user *) (arg + offsetof(struct ib_user_mad_reg_req, id)))) {
ret = -EFAULT;
- goto err_mr;
+ ib_unregister_mad_agent(agent);
+ goto out;
}
+ file->agent[agent_id] = agent;
ret = 0;
- goto out;
-
-err_mr:
- ib_dereg_mr(file->mr[agent_id]);
-
-err:
- file->agent[agent_id] = NULL;
- ib_unregister_mad_agent(agent);
out:
up_write(&file->port->mutex);
@@ -536,27 +529,29 @@ out:
static int ib_umad_unreg_agent(struct ib_umad_file *file, unsigned long arg)
{
+ struct ib_mad_agent *agent = NULL;
u32 id;
int ret = 0;
- down_write(&file->port->mutex);
+ if (get_user(id, (u32 __user *) arg))
+ return -EFAULT;
- if (get_user(id, (u32 __user *) arg)) {
- ret = -EFAULT;
- goto out;
- }
+ down_write(&file->port->mutex);
- if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !file->agent[id]) {
+ if (id < 0 || id >= IB_UMAD_MAX_AGENTS || !__get_agent(file, id)) {
ret = -EINVAL;
goto out;
}
- ib_dereg_mr(file->mr[id]);
- ib_unregister_mad_agent(file->agent[id]);
+ agent = file->agent[id];
file->agent[id] = NULL;
out:
up_write(&file->port->mutex);
+
+ if (agent)
+ ib_unregister_mad_agent(agent);
+
return ret;
}
@@ -621,23 +616,29 @@ static int ib_umad_close(struct inode *inode, struct file *filp)
struct ib_umad_file *file = filp->private_data;
struct ib_umad_device *dev = file->port->umad_dev;
struct ib_umad_packet *packet, *tmp;
+ int already_dead;
int i;
down_write(&file->port->mutex);
- for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i)
- if (file->agent[i]) {
- ib_dereg_mr(file->mr[i]);
- ib_unregister_mad_agent(file->agent[i]);
- }
+
+ already_dead = file->agents_dead;
+ file->agents_dead = 1;
list_for_each_entry_safe(packet, tmp, &file->recv_list, list)
kfree(packet);
list_del(&file->port_list);
- up_write(&file->port->mutex);
- kfree(file);
+ downgrade_write(&file->port->mutex);
+
+ if (!already_dead)
+ for (i = 0; i < IB_UMAD_MAX_AGENTS; ++i)
+ if (file->agent[i])
+ ib_unregister_mad_agent(file->agent[i]);
+
+ up_read(&file->port->mutex);
+ kfree(file);
kref_put(&dev->ref, ib_umad_release_dev);
return 0;
@@ -801,7 +802,7 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
goto err_class;
port->sm_dev->owner = THIS_MODULE;
port->sm_dev->ops = &umad_sm_fops;
- kobject_set_name(&port->dev->kobj, "issm%d", port->dev_num);
+ kobject_set_name(&port->sm_dev->kobj, "issm%d", port->dev_num);
if (cdev_add(port->sm_dev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
goto err_sm_cdev;
@@ -863,14 +864,36 @@ static void ib_umad_kill_port(struct ib_umad_port *port)
port->ib_dev = NULL;
- list_for_each_entry(file, &port->file_list, port_list)
- for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id) {
- if (!file->agent[id])
- continue;
- ib_dereg_mr(file->mr[id]);
- ib_unregister_mad_agent(file->agent[id]);
- file->agent[id] = NULL;
- }
+ /*
+ * Now go through the list of files attached to this port and
+ * unregister all of their MAD agents. We need to hold
+ * port->mutex while doing this to avoid racing with
+ * ib_umad_close(), but we can't hold the mutex for writing
+ * while calling ib_unregister_mad_agent(), since that might
+ * deadlock by calling back into queue_packet(). So we
+ * downgrade our lock to a read lock, and then drop and
+ * reacquire the write lock for the next iteration.
+ *
+ * We do list_del_init() on the file's list_head so that the
+ * list_del in ib_umad_close() is still OK, even after the
+ * file is removed from the list.
+ */
+ while (!list_empty(&port->file_list)) {
+ file = list_entry(port->file_list.next, struct ib_umad_file,
+ port_list);
+
+ file->agents_dead = 1;
+ list_del_init(&file->port_list);
+
+ downgrade_write(&port->mutex);
+
+ for (id = 0; id < IB_UMAD_MAX_AGENTS; ++id)
+ if (file->agent[id])
+ ib_unregister_mad_agent(file->agent[id]);
+
+ up_read(&port->mutex);
+ down_write(&port->mutex);
+ }
up_write(&port->mutex);
@@ -913,7 +936,7 @@ static void ib_umad_add_one(struct ib_device *device)
err:
while (--i >= s)
- ib_umad_kill_port(&umad_dev->port[i]);
+ ib_umad_kill_port(&umad_dev->port[i - s]);
kref_put(&umad_dev->ref, ib_umad_release_dev);
}
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 63a74151c60b..ed45da892b1c 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -708,7 +708,7 @@ ssize_t ib_uverbs_poll_cq(struct ib_uverbs_file *file,
resp->wc[i].opcode = wc[i].opcode;
resp->wc[i].vendor_err = wc[i].vendor_err;
resp->wc[i].byte_len = wc[i].byte_len;
- resp->wc[i].imm_data = wc[i].imm_data;
+ resp->wc[i].imm_data = (__u32 __force) wc[i].imm_data;
resp->wc[i].qp_num = wc[i].qp_num;
resp->wc[i].src_qp = wc[i].src_qp;
resp->wc[i].wc_flags = wc[i].wc_flags;
@@ -908,7 +908,12 @@ retry:
if (ret)
goto err_destroy;
- resp.qp_handle = uobj->uobject.id;
+ resp.qp_handle = uobj->uobject.id;
+ resp.max_recv_sge = attr.cap.max_recv_sge;
+ resp.max_send_sge = attr.cap.max_send_sge;
+ resp.max_recv_wr = attr.cap.max_recv_wr;
+ resp.max_send_wr = attr.cap.max_send_wr;
+ resp.max_inline_data = attr.cap.max_inline_data;
if (copy_to_user((void __user *) (unsigned long) cmd.response,
&resp, sizeof resp)) {
@@ -1135,7 +1140,7 @@ ssize_t ib_uverbs_post_send(struct ib_uverbs_file *file,
next->num_sge = user_wr->num_sge;
next->opcode = user_wr->opcode;
next->send_flags = user_wr->send_flags;
- next->imm_data = user_wr->imm_data;
+ next->imm_data = (__be32 __force) user_wr->imm_data;
if (qp->qp_type == IB_QPT_UD) {
next->wr.ud.ah = idr_find(&ib_uverbs_ah_idr,
@@ -1701,7 +1706,6 @@ ssize_t ib_uverbs_modify_srq(struct ib_uverbs_file *file,
}
attr.max_wr = cmd.max_wr;
- attr.max_sge = cmd.max_sge;
attr.srq_limit = cmd.srq_limit;
ret = ib_modify_srq(srq, &attr, cmd.attr_mask);
diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c
index 4186cc888ea5..4c15e112736c 100644
--- a/drivers/infiniband/core/verbs.c
+++ b/drivers/infiniband/core/verbs.c
@@ -325,16 +325,8 @@ EXPORT_SYMBOL(ib_destroy_cq);
int ib_resize_cq(struct ib_cq *cq,
int cqe)
{
- int ret;
-
- if (!cq->device->resize_cq)
- return -ENOSYS;
-
- ret = cq->device->resize_cq(cq, &cqe);
- if (!ret)
- cq->cqe = cqe;
-
- return ret;
+ return cq->device->resize_cq ?
+ cq->device->resize_cq(cq, cqe) : -ENOSYS;
}
EXPORT_SYMBOL(ib_resize_cq);
diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c
index 25ebab64bc42..c3bec7490f52 100644
--- a/drivers/infiniband/hw/mthca/mthca_catas.c
+++ b/drivers/infiniband/hw/mthca/mthca_catas.c
@@ -97,7 +97,7 @@ static void poll_catas(unsigned long dev_ptr)
}
spin_lock_irqsave(&catas_lock, flags);
- if (dev->catas_err.stop)
+ if (!dev->catas_err.stop)
mod_timer(&dev->catas_err.timer,
jiffies + MTHCA_CATAS_POLL_INTERVAL);
spin_unlock_irqrestore(&catas_lock, flags);
diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c
index 49f211d55df7..9ed34587fc5c 100644
--- a/drivers/infiniband/hw/mthca/mthca_cmd.c
+++ b/drivers/infiniband/hw/mthca/mthca_cmd.c
@@ -1060,6 +1060,8 @@ int mthca_QUERY_DEV_LIM(struct mthca_dev *dev,
dev_lim->hca.arbel.resize_srq = field & 1;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_MAX_SG_RQ_OFFSET);
dev_lim->max_sg = min_t(int, field, dev_lim->max_sg);
+ MTHCA_GET(size, outbox, QUERY_DEV_LIM_MAX_DESC_SZ_RQ_OFFSET);
+ dev_lim->max_desc_sz = min_t(int, size, dev_lim->max_desc_sz);
MTHCA_GET(size, outbox, QUERY_DEV_LIM_MPT_ENTRY_SZ_OFFSET);
dev_lim->mpt_entry_sz = size;
MTHCA_GET(field, outbox, QUERY_DEV_LIM_PBL_SZ_OFFSET);
diff --git a/drivers/infiniband/hw/mthca/mthca_cq.c b/drivers/infiniband/hw/mthca/mthca_cq.c
index f98e23555826..4a8adcef2079 100644
--- a/drivers/infiniband/hw/mthca/mthca_cq.c
+++ b/drivers/infiniband/hw/mthca/mthca_cq.c
@@ -258,7 +258,7 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
{
struct mthca_cq *cq;
struct mthca_cqe *cqe;
- int prod_index;
+ u32 prod_index;
int nfreed = 0;
spin_lock_irq(&dev->cq_table.lock);
@@ -293,19 +293,15 @@ void mthca_cq_clean(struct mthca_dev *dev, u32 cqn, u32 qpn,
* Now sweep backwards through the CQ, removing CQ entries
* that match our QP by copying older entries on top of them.
*/
- while (prod_index > cq->cons_index) {
- cqe = get_cqe(cq, (prod_index - 1) & cq->ibcq.cqe);
+ while ((int) --prod_index - (int) cq->cons_index >= 0) {
+ cqe = get_cqe(cq, prod_index & cq->ibcq.cqe);
if (cqe->my_qpn == cpu_to_be32(qpn)) {
if (srq)
mthca_free_srq_wqe(srq, be32_to_cpu(cqe->wqe));
++nfreed;
- }
- else if (nfreed)
- memcpy(get_cqe(cq, (prod_index - 1 + nfreed) &
- cq->ibcq.cqe),
- cqe,
- MTHCA_CQ_ENTRY_SIZE);
- --prod_index;
+ } else if (nfreed)
+ memcpy(get_cqe(cq, (prod_index + nfreed) & cq->ibcq.cqe),
+ cqe, MTHCA_CQ_ENTRY_SIZE);
}
if (nfreed) {
diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h
index e7e5d3b4f004..497ff794ef6a 100644
--- a/drivers/infiniband/hw/mthca/mthca_dev.h
+++ b/drivers/infiniband/hw/mthca/mthca_dev.h
@@ -131,6 +131,7 @@ struct mthca_limits {
int max_sg;
int num_qps;
int max_wqes;
+ int max_desc_sz;
int max_qp_init_rdma;
int reserved_qps;
int num_srqs;
@@ -154,6 +155,7 @@ struct mthca_limits {
int reserved_mcgs;
int num_pds;
int reserved_pds;
+ u32 page_size_cap;
u32 flags;
u8 port_width_cap;
};
diff --git a/drivers/infiniband/hw/mthca/mthca_main.c b/drivers/infiniband/hw/mthca/mthca_main.c
index 45c6328e780c..6f94b25f3acd 100644
--- a/drivers/infiniband/hw/mthca/mthca_main.c
+++ b/drivers/infiniband/hw/mthca/mthca_main.c
@@ -168,6 +168,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
mdev->limits.max_srq_wqes = dev_lim->max_srq_sz;
mdev->limits.reserved_srqs = dev_lim->reserved_srqs;
mdev->limits.reserved_eecs = dev_lim->reserved_eecs;
+ mdev->limits.max_desc_sz = dev_lim->max_desc_sz;
/*
* Subtract 1 from the limit because we need to allocate a
* spare CQE so the HCA HW can tell the difference between an
@@ -181,6 +182,7 @@ static int __devinit mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim
mdev->limits.reserved_uars = dev_lim->reserved_uars;
mdev->limits.reserved_pds = dev_lim->reserved_pds;
mdev->limits.port_width_cap = dev_lim->max_port_width;
+ mdev->limits.page_size_cap = ~(u32) (dev_lim->min_page_sz - 1);
mdev->limits.flags = dev_lim->flags;
/* IB_DEVICE_RESIZE_MAX_WR not supported by driver.
@@ -1196,7 +1198,6 @@ MODULE_DEVICE_TABLE(pci, mthca_pci_table);
static struct pci_driver mthca_driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
.id_table = mthca_pci_table,
.probe = mthca_init_one,
.remove = __devexit_p(mthca_remove_one)
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c
index 6b0166668269..4cc7e2846df1 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.c
+++ b/drivers/infiniband/hw/mthca/mthca_provider.c
@@ -90,6 +90,7 @@ static int mthca_query_device(struct ib_device *ibdev,
memcpy(&props->node_guid, out_mad->data + 12, 8);
props->max_mr_size = ~0ull;
+ props->page_size_cap = mdev->limits.page_size_cap;
props->max_qp = mdev->limits.num_qps - mdev->limits.reserved_qps;
props->max_qp_wr = mdev->limits.max_wqes;
props->max_sge = mdev->limits.max_sg;
@@ -615,11 +616,11 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
return ERR_PTR(err);
}
- init_attr->cap.max_inline_data = 0;
init_attr->cap.max_send_wr = qp->sq.max;
init_attr->cap.max_recv_wr = qp->rq.max;
init_attr->cap.max_send_sge = qp->sq.max_gs;
init_attr->cap.max_recv_sge = qp->rq.max_gs;
+ init_attr->cap.max_inline_data = qp->max_inline_data;
return &qp->ibqp;
}
diff --git a/drivers/infiniband/hw/mthca/mthca_provider.h b/drivers/infiniband/hw/mthca/mthca_provider.h
index bcd4b01a339c..1e73947b4702 100644
--- a/drivers/infiniband/hw/mthca/mthca_provider.h
+++ b/drivers/infiniband/hw/mthca/mthca_provider.h
@@ -251,6 +251,7 @@ struct mthca_qp {
struct mthca_wq sq;
enum ib_sig_type sq_policy;
int send_wqe_offset;
+ int max_inline_data;
u64 *wrid;
union mthca_buf queue;
diff --git a/drivers/infiniband/hw/mthca/mthca_qp.c b/drivers/infiniband/hw/mthca/mthca_qp.c
index 8852ea477c21..760c418d5bc9 100644
--- a/drivers/infiniband/hw/mthca/mthca_qp.c
+++ b/drivers/infiniband/hw/mthca/mthca_qp.c
@@ -885,6 +885,48 @@ int mthca_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask)
return err;
}
+static void mthca_adjust_qp_caps(struct mthca_dev *dev,
+ struct mthca_pd *pd,
+ struct mthca_qp *qp)
+{
+ int max_data_size;
+
+ /*
+ * Calculate the maximum size of WQE s/g segments, excluding
+ * the next segment and other non-data segments.
+ */
+ max_data_size = min(dev->limits.max_desc_sz, 1 << qp->sq.wqe_shift) -
+ sizeof (struct mthca_next_seg);
+
+ switch (qp->transport) {
+ case MLX:
+ max_data_size -= 2 * sizeof (struct mthca_data_seg);
+ break;
+
+ case UD:
+ if (mthca_is_memfree(dev))
+ max_data_size -= sizeof (struct mthca_arbel_ud_seg);
+ else
+ max_data_size -= sizeof (struct mthca_tavor_ud_seg);
+ break;
+
+ default:
+ max_data_size -= sizeof (struct mthca_raddr_seg);
+ break;
+ }
+
+ /* We don't support inline data for kernel QPs (yet). */
+ if (!pd->ibpd.uobject)
+ qp->max_inline_data = 0;
+ else
+ qp->max_inline_data = max_data_size - MTHCA_INLINE_HEADER_SIZE;
+
+ qp->sq.max_gs = max_data_size / sizeof (struct mthca_data_seg);
+ qp->rq.max_gs = (min(dev->limits.max_desc_sz, 1 << qp->rq.wqe_shift) -
+ sizeof (struct mthca_next_seg)) /
+ sizeof (struct mthca_data_seg);
+}
+
/*
* Allocate and register buffer for WQEs. qp->rq.max, sq.max,
* rq.max_gs and sq.max_gs must all be assigned.
@@ -902,27 +944,53 @@ static int mthca_alloc_wqe_buf(struct mthca_dev *dev,
size = sizeof (struct mthca_next_seg) +
qp->rq.max_gs * sizeof (struct mthca_data_seg);
+ if (size > dev->limits.max_desc_sz)
+ return -EINVAL;
+
for (qp->rq.wqe_shift = 6; 1 << qp->rq.wqe_shift < size;
qp->rq.wqe_shift++)
; /* nothing */
- size = sizeof (struct mthca_next_seg) +
- qp->sq.max_gs * sizeof (struct mthca_data_seg);
+ size = qp->sq.max_gs * sizeof (struct mthca_data_seg);
switch (qp->transport) {
case MLX:
size += 2 * sizeof (struct mthca_data_seg);
break;
+
case UD:
- if (mthca_is_memfree(dev))
- size += sizeof (struct mthca_arbel_ud_seg);
- else
- size += sizeof (struct mthca_tavor_ud_seg);
+ size += mthca_is_memfree(dev) ?
+ sizeof (struct mthca_arbel_ud_seg) :
+ sizeof (struct mthca_tavor_ud_seg);
break;
+
+ case UC:
+ size += sizeof (struct mthca_raddr_seg);
+ break;
+
+ case RC:
+ size += sizeof (struct mthca_raddr_seg);
+ /*
+ * An atomic op will require an atomic segment, a
+ * remote address segment and one scatter entry.
+ */
+ size = max_t(int, size,
+ sizeof (struct mthca_atomic_seg) +
+ sizeof (struct mthca_raddr_seg) +
+ sizeof (struct mthca_data_seg));
+ break;
+
default:
- /* bind seg is as big as atomic + raddr segs */
- size += sizeof (struct mthca_bind_seg);
+ break;
}
+ /* Make sure that we have enough space for a bind request */
+ size = max_t(int, size, sizeof (struct mthca_bind_seg));
+
+ size += sizeof (struct mthca_next_seg);
+
+ if (size > dev->limits.max_desc_sz)
+ return -EINVAL;
+
for (qp->sq.wqe_shift = 6; 1 << qp->sq.wqe_shift < size;
qp->sq.wqe_shift++)
; /* nothing */
@@ -1066,6 +1134,8 @@ static int mthca_alloc_qp_common(struct mthca_dev *dev,
return ret;
}
+ mthca_adjust_qp_caps(dev, pd, qp);
+
/*
* If this is a userspace QP, we're done now. The doorbells
* will be allocated and buffers will be initialized in
@@ -1486,8 +1556,8 @@ int mthca_tavor_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
}
wqe += sizeof (struct mthca_atomic_seg);
- size += sizeof (struct mthca_raddr_seg) / 16 +
- sizeof (struct mthca_atomic_seg);
+ size += (sizeof (struct mthca_raddr_seg) +
+ sizeof (struct mthca_atomic_seg)) / 16;
break;
case IB_WR_RDMA_WRITE:
@@ -1637,6 +1707,7 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
{
struct mthca_dev *dev = to_mdev(ibqp->device);
struct mthca_qp *qp = to_mqp(ibqp);
+ __be32 doorbell[2];
unsigned long flags;
int err = 0;
int nreq;
@@ -1654,6 +1725,22 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
ind = qp->rq.next_ind;
for (nreq = 0; wr; ++nreq, wr = wr->next) {
+ if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
+ nreq = 0;
+
+ doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
+ doorbell[1] = cpu_to_be32(qp->qpn << 8);
+
+ wmb();
+
+ mthca_write64(doorbell,
+ dev->kar + MTHCA_RECEIVE_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+
+ qp->rq.head += MTHCA_TAVOR_MAX_WQES_PER_RECV_DB;
+ size0 = 0;
+ }
+
if (mthca_wq_overflow(&qp->rq, nreq, qp->ibqp.recv_cq)) {
mthca_err(dev, "RQ %06x full (%u head, %u tail,"
" %d max, %d nreq)\n", qp->qpn,
@@ -1711,8 +1798,6 @@ int mthca_tavor_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
out:
if (likely(nreq)) {
- __be32 doorbell[2];
-
doorbell[0] = cpu_to_be32((qp->rq.next_ind << qp->rq.wqe_shift) | size0);
doorbell[1] = cpu_to_be32((qp->qpn << 8) | nreq);
@@ -1806,8 +1891,8 @@ int mthca_arbel_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
}
wqe += sizeof (struct mthca_atomic_seg);
- size += sizeof (struct mthca_raddr_seg) / 16 +
- sizeof (struct mthca_atomic_seg);
+ size += (sizeof (struct mthca_raddr_seg) +
+ sizeof (struct mthca_atomic_seg)) / 16;
break;
case IB_WR_RDMA_READ:
diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c
index 26d5161fde07..f7d234295efe 100644
--- a/drivers/infiniband/hw/mthca/mthca_srq.c
+++ b/drivers/infiniband/hw/mthca/mthca_srq.c
@@ -417,6 +417,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
{
struct mthca_dev *dev = to_mdev(ibsrq->device);
struct mthca_srq *srq = to_msrq(ibsrq);
+ __be32 doorbell[2];
unsigned long flags;
int err = 0;
int first_ind;
@@ -432,6 +433,25 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
first_ind = srq->first_free;
for (nreq = 0; wr; ++nreq, wr = wr->next) {
+ if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) {
+ nreq = 0;
+
+ doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
+ doorbell[1] = cpu_to_be32(srq->srqn << 8);
+
+ /*
+ * Make sure that descriptors are written
+ * before doorbell is rung.
+ */
+ wmb();
+
+ mthca_write64(doorbell,
+ dev->kar + MTHCA_RECEIVE_DOORBELL,
+ MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock));
+
+ first_ind = srq->first_free;
+ }
+
ind = srq->first_free;
if (ind < 0) {
@@ -494,8 +514,6 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr,
}
if (likely(nreq)) {
- __be32 doorbell[2];
-
doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift);
doorbell[1] = cpu_to_be32((srq->srqn << 8) | nreq);
diff --git a/drivers/infiniband/hw/mthca/mthca_wqe.h b/drivers/infiniband/hw/mthca/mthca_wqe.h
index 1f4c0ff28f79..73f1c0b9021e 100644
--- a/drivers/infiniband/hw/mthca/mthca_wqe.h
+++ b/drivers/infiniband/hw/mthca/mthca_wqe.h
@@ -49,7 +49,8 @@ enum {
};
enum {
- MTHCA_INVAL_LKEY = 0x100
+ MTHCA_INVAL_LKEY = 0x100,
+ MTHCA_TAVOR_MAX_WQES_PER_RECV_DB = 256
};
struct mthca_next_seg {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 0095acc0fbbe..9923a15a9996 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -179,6 +179,7 @@ struct ipoib_dev_priv {
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
struct list_head fs_list;
struct dentry *mcg_dentry;
+ struct dentry *path_dentry;
#endif
};
@@ -270,7 +271,6 @@ void ipoib_mcast_dev_flush(struct net_device *dev);
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev);
-void ipoib_mcast_iter_free(struct ipoib_mcast_iter *iter);
int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter);
void ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter,
union ib_gid *gid,
@@ -278,6 +278,11 @@ void ipoib_mcast_iter_read(struct ipoib_mcast_iter *iter,
unsigned int *queuelen,
unsigned int *complete,
unsigned int *send_only);
+
+struct ipoib_path_iter *ipoib_path_iter_init(struct net_device *dev);
+int ipoib_path_iter_next(struct ipoib_path_iter *iter);
+void ipoib_path_iter_read(struct ipoib_path_iter *iter,
+ struct ipoib_path *path);
#endif
int ipoib_mcast_attach(struct net_device *dev, u16 mlid,
@@ -299,13 +304,13 @@ void ipoib_pkey_poll(void *dev);
int ipoib_pkey_dev_delay_open(struct net_device *dev);
#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
-int ipoib_create_debug_file(struct net_device *dev);
-void ipoib_delete_debug_file(struct net_device *dev);
+void ipoib_create_debug_files(struct net_device *dev);
+void ipoib_delete_debug_files(struct net_device *dev);
int ipoib_register_debugfs(void);
void ipoib_unregister_debugfs(void);
#else
-static inline int ipoib_create_debug_file(struct net_device *dev) { return 0; }
-static inline void ipoib_delete_debug_file(struct net_device *dev) { }
+static inline void ipoib_create_debug_files(struct net_device *dev) { }
+static inline void ipoib_delete_debug_files(struct net_device *dev) { }
static inline int ipoib_register_debugfs(void) { return 0; }
static inline void ipoib_unregister_debugfs(void) { }
#endif
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_fs.c b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
index 38b150f775e7..685258e34034 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_fs.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_fs.c
@@ -43,6 +43,18 @@ struct file_operations;
static struct dentry *ipoib_root;
+static void format_gid(union ib_gid *gid, char *buf)
+{
+ int i, n;
+
+ for (n = 0, i = 0; i < 8; ++i) {
+ n += sprintf(buf + n, "%x",
+ be16_to_cpu(((__be16 *) gid->raw)[i]));
+ if (i < 7)
+ buf[n++] = ':';
+ }
+}
+
static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos)
{
struct ipoib_mcast_iter *iter;
@@ -54,7 +66,7 @@ static void *ipoib_mcg_seq_start(struct seq_file *file, loff_t *pos)
while (n--) {
if (ipoib_mcast_iter_next(iter)) {
- ipoib_mcast_iter_free(iter);
+ kfree(iter);
return NULL;
}
}
@@ -70,7 +82,7 @@ static void *ipoib_mcg_seq_next(struct seq_file *file, void *iter_ptr,
(*pos)++;
if (ipoib_mcast_iter_next(iter)) {
- ipoib_mcast_iter_free(iter);
+ kfree(iter);
return NULL;
}
@@ -87,32 +99,32 @@ static int ipoib_mcg_seq_show(struct seq_file *file, void *iter_ptr)
struct ipoib_mcast_iter *iter = iter_ptr;
char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
union ib_gid mgid;
- int i, n;
unsigned long created;
unsigned int queuelen, complete, send_only;
- if (iter) {
- ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen,
- &complete, &send_only);
+ if (!iter)
+ return 0;
- for (n = 0, i = 0; i < sizeof mgid / 2; ++i) {
- n += sprintf(gid_buf + n, "%x",
- be16_to_cpu(((__be16 *) mgid.raw)[i]));
- if (i < sizeof mgid / 2 - 1)
- gid_buf[n++] = ':';
- }
- }
+ ipoib_mcast_iter_read(iter, &mgid, &created, &queuelen,
+ &complete, &send_only);
- seq_printf(file, "GID: %*s", -(1 + (int) sizeof gid_buf), gid_buf);
+ format_gid(&mgid, gid_buf);
seq_printf(file,
- " created: %10ld queuelen: %4d complete: %d send_only: %d\n",
- created, queuelen, complete, send_only);
+ "GID: %s\n"
+ " created: %10ld\n"
+ " queuelen: %9d\n"
+ " complete: %9s\n"
+ " send_only: %8s\n"
+ "\n",
+ gid_buf, created, queuelen,
+ complete ? "yes" : "no",
+ send_only ? "yes" : "no");
return 0;
}
-static struct seq_operations ipoib_seq_ops = {
+static struct seq_operations ipoib_mcg_seq_ops = {
.start = ipoib_mcg_seq_start,
.next = ipoib_mcg_seq_next,
.stop = ipoib_mcg_seq_stop,
@@ -124,7 +136,7 @@ static int ipoib_mcg_open(struct inode *inode, struct file *file)
struct seq_file *seq;
int ret;
- ret = seq_open(file, &ipoib_seq_ops);
+ ret = seq_open(file, &ipoib_mcg_seq_ops);
if (ret)
return ret;
@@ -134,7 +146,7 @@ static int ipoib_mcg_open(struct inode *inode, struct file *file)
return 0;
}
-static struct file_operations ipoib_fops = {
+static struct file_operations ipoib_mcg_fops = {
.owner = THIS_MODULE,
.open = ipoib_mcg_open,
.read = seq_read,
@@ -142,25 +154,138 @@ static struct file_operations ipoib_fops = {
.release = seq_release
};
-int ipoib_create_debug_file(struct net_device *dev)
+static void *ipoib_path_seq_start(struct seq_file *file, loff_t *pos)
+{
+ struct ipoib_path_iter *iter;
+ loff_t n = *pos;
+
+ iter = ipoib_path_iter_init(file->private);
+ if (!iter)
+ return NULL;
+
+ while (n--) {
+ if (ipoib_path_iter_next(iter)) {
+ kfree(iter);
+ return NULL;
+ }
+ }
+
+ return iter;
+}
+
+static void *ipoib_path_seq_next(struct seq_file *file, void *iter_ptr,
+ loff_t *pos)
+{
+ struct ipoib_path_iter *iter = iter_ptr;
+
+ (*pos)++;
+
+ if (ipoib_path_iter_next(iter)) {
+ kfree(iter);
+ return NULL;
+ }
+
+ return iter;
+}
+
+static void ipoib_path_seq_stop(struct seq_file *file, void *iter_ptr)
+{
+ /* nothing for now */
+}
+
+static int ipoib_path_seq_show(struct seq_file *file, void *iter_ptr)
+{
+ struct ipoib_path_iter *iter = iter_ptr;
+ char gid_buf[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"];
+ struct ipoib_path path;
+ int rate;
+
+ if (!iter)
+ return 0;
+
+ ipoib_path_iter_read(iter, &path);
+
+ format_gid(&path.pathrec.dgid, gid_buf);
+
+ seq_printf(file,
+ "GID: %s\n"
+ " complete: %6s\n",
+ gid_buf, path.pathrec.dlid ? "yes" : "no");
+
+ if (path.pathrec.dlid) {
+ rate = ib_sa_rate_enum_to_int(path.pathrec.rate) * 25;
+
+ seq_printf(file,
+ " DLID: 0x%04x\n"
+ " SL: %12d\n"
+ " rate: %*d%s Gb/sec\n",
+ be16_to_cpu(path.pathrec.dlid),
+ path.pathrec.sl,
+ 10 - ((rate % 10) ? 2 : 0),
+ rate / 10, rate % 10 ? ".5" : "");
+ }
+
+ seq_putc(file, '\n');
+
+ return 0;
+}
+
+static struct seq_operations ipoib_path_seq_ops = {
+ .start = ipoib_path_seq_start,
+ .next = ipoib_path_seq_next,
+ .stop = ipoib_path_seq_stop,
+ .show = ipoib_path_seq_show,
+};
+
+static int ipoib_path_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ int ret;
+
+ ret = seq_open(file, &ipoib_path_seq_ops);
+ if (ret)
+ return ret;
+
+ seq = file->private_data;
+ seq->private = inode->u.generic_ip;
+
+ return 0;
+}
+
+static struct file_operations ipoib_path_fops = {
+ .owner = THIS_MODULE,
+ .open = ipoib_path_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+void ipoib_create_debug_files(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
- char name[IFNAMSIZ + sizeof "_mcg"];
+ char name[IFNAMSIZ + sizeof "_path"];
snprintf(name, sizeof name, "%s_mcg", dev->name);
-
priv->mcg_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
- ipoib_root, dev, &ipoib_fops);
-
- return priv->mcg_dentry ? 0 : -ENOMEM;
+ ipoib_root, dev, &ipoib_mcg_fops);
+ if (!priv->mcg_dentry)
+ ipoib_warn(priv, "failed to create mcg debug file\n");
+
+ snprintf(name, sizeof name, "%s_path", dev->name);
+ priv->path_dentry = debugfs_create_file(name, S_IFREG | S_IRUGO,
+ ipoib_root, dev, &ipoib_path_fops);
+ if (!priv->path_dentry)
+ ipoib_warn(priv, "failed to create path debug file\n");
}
-void ipoib_delete_debug_file(struct net_device *dev)
+void ipoib_delete_debug_files(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
if (priv->mcg_dentry)
debugfs_remove(priv->mcg_dentry);
+ if (priv->path_dentry)
+ debugfs_remove(priv->path_dentry);
}
int ipoib_register_debugfs(void)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index ce0296273e76..2fa30751f362 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -58,6 +58,11 @@ module_param_named(debug_level, ipoib_debug_level, int, 0644);
MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0");
#endif
+struct ipoib_path_iter {
+ struct net_device *dev;
+ struct ipoib_path path;
+};
+
static const u8 ipv4_bcast_addr[] = {
0x00, 0xff, 0xff, 0xff,
0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
@@ -250,6 +255,64 @@ static void path_free(struct net_device *dev, struct ipoib_path *path)
kfree(path);
}
+#ifdef CONFIG_INFINIBAND_IPOIB_DEBUG
+
+struct ipoib_path_iter *ipoib_path_iter_init(struct net_device *dev)
+{
+ struct ipoib_path_iter *iter;
+
+ iter = kmalloc(sizeof *iter, GFP_KERNEL);
+ if (!iter)
+ return NULL;
+
+ iter->dev = dev;
+ memset(iter->path.pathrec.dgid.raw, 0, 16);
+
+ if (ipoib_path_iter_next(iter)) {
+ kfree(iter);
+ return NULL;
+ }
+
+ return iter;
+}
+
+int ipoib_path_iter_next(struct ipoib_path_iter *iter)
+{
+ struct ipoib_dev_priv *priv = netdev_priv(iter->dev);
+ struct rb_node *n;
+ struct ipoib_path *path;
+ int ret = 1;
+
+ spin_lock_irq(&priv->lock);
+
+ n = rb_first(&priv->path_tree);
+
+ while (n) {
+ path = rb_entry(n, struct ipoib_path, rb_node);
+
+ if (memcmp(iter->path.pathrec.dgid.raw, path->pathrec.dgid.raw,
+ sizeof (union ib_gid)) < 0) {
+ iter->path = *path;
+ ret = 0;
+ break;
+ }
+
+ n = rb_next(n);
+ }
+
+ spin_unlock_irq(&priv->lock);
+
+ return ret;
+}
+
+void ipoib_path_iter_read(struct ipoib_path_iter *iter,
+ struct ipoib_path *path)
+{
+ *path = iter->path;
+}
+
+#endif /* CONFIG_INFINIBAND_IPOIB_DEBUG */
+
void ipoib_flush_paths(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -763,7 +826,7 @@ void ipoib_dev_cleanup(struct net_device *dev)
{
struct ipoib_dev_priv *priv = netdev_priv(dev), *cpriv, *tcpriv;
- ipoib_delete_debug_file(dev);
+ ipoib_delete_debug_files(dev);
/* Delete any child interfaces first */
list_for_each_entry_safe(cpriv, tcpriv, &priv->child_intfs, list) {
@@ -972,8 +1035,7 @@ static struct net_device *ipoib_add_port(const char *format,
goto register_failed;
}
- if (ipoib_create_debug_file(priv->dev))
- goto debug_failed;
+ ipoib_create_debug_files(priv->dev);
if (ipoib_add_pkey_attr(priv->dev))
goto sysfs_failed;
@@ -987,9 +1049,7 @@ static struct net_device *ipoib_add_port(const char *format,
return priv->dev;
sysfs_failed:
- ipoib_delete_debug_file(priv->dev);
-
-debug_failed:
+ ipoib_delete_debug_files(priv->dev);
unregister_netdev(priv->dev);
register_failed:
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
index 3ecf78a9493a..c33ed87f9dff 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c
@@ -120,12 +120,8 @@ static void ipoib_mcast_free(struct ipoib_mcast *mcast)
if (mcast->ah)
ipoib_put_ah(mcast->ah);
- while (!skb_queue_empty(&mcast->pkt_queue)) {
- struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
-
- skb->dev = dev;
- dev_kfree_skb_any(skb);
- }
+ while (!skb_queue_empty(&mcast->pkt_queue))
+ dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
kfree(mcast);
}
@@ -317,13 +313,8 @@ ipoib_mcast_sendonly_join_complete(int status,
IPOIB_GID_ARG(mcast->mcmember.mgid), status);
/* Flush out any queued packets */
- while (!skb_queue_empty(&mcast->pkt_queue)) {
- struct sk_buff *skb = skb_dequeue(&mcast->pkt_queue);
-
- skb->dev = dev;
-
- dev_kfree_skb_any(skb);
- }
+ while (!skb_queue_empty(&mcast->pkt_queue))
+ dev_kfree_skb_any(skb_dequeue(&mcast->pkt_queue));
/* Clear the busy flag so we try again */
clear_bit(IPOIB_MCAST_FLAG_BUSY, &mcast->flags);
@@ -928,21 +919,16 @@ struct ipoib_mcast_iter *ipoib_mcast_iter_init(struct net_device *dev)
return NULL;
iter->dev = dev;
- memset(iter->mgid.raw, 0, sizeof iter->mgid);
+ memset(iter->mgid.raw, 0, 16);
if (ipoib_mcast_iter_next(iter)) {
- ipoib_mcast_iter_free(iter);
+ kfree(iter);
return NULL;
}
return iter;
}
-void ipoib_mcast_iter_free(struct ipoib_mcast_iter *iter)
-{
- kfree(iter);
-}
-
int ipoib_mcast_iter_next(struct ipoib_mcast_iter *iter)
{
struct ipoib_dev_priv *priv = netdev_priv(iter->dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
index 332d730e60c2..d280b341a37f 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_vlan.c
@@ -113,8 +113,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
priv->parent = ppriv->dev;
- if (ipoib_create_debug_file(priv->dev))
- goto debug_failed;
+ ipoib_create_debug_files(priv->dev);
if (ipoib_add_pkey_attr(priv->dev))
goto sysfs_failed;
@@ -130,9 +129,7 @@ int ipoib_vlan_add(struct net_device *pdev, unsigned short pkey)
return 0;
sysfs_failed:
- ipoib_delete_debug_file(priv->dev);
-
-debug_failed:
+ ipoib_delete_debug_files(priv->dev);
unregister_netdev(priv->dev);
register_failed:
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c
index 8f464271664d..49fa1e4413fa 100644
--- a/drivers/net/bnx2.c
+++ b/drivers/net/bnx2.c
@@ -2707,7 +2707,7 @@ bnx2_init_nvram(struct bnx2 *bp)
if (j == entry_count) {
bp->flash_info = NULL;
- printk(KERN_ALERT "Unknown flash/EEPROM type.\n");
+ printk(KERN_ALERT PFX "Unknown flash/EEPROM type.\n");
rc = -ENODEV;
}
@@ -3903,6 +3903,8 @@ bnx2_test_loopback(struct bnx2 *bp)
pkt_size = 1514;
skb = dev_alloc_skb(pkt_size);
+ if (!skb)
+ return -ENOMEM;
packet = skb_put(skb, pkt_size);
memcpy(packet, bp->mac_addr, 6);
memset(packet + 6, 0x0, 8);
@@ -4798,11 +4800,7 @@ bnx2_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
struct bnx2 *bp = dev->priv;
int rc;
- if (eeprom->offset > bp->flash_info->total_size)
- return -EINVAL;
-
- if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size)
- eeprom->len = bp->flash_info->total_size - eeprom->offset;
+ /* parameters already validated in ethtool_get_eeprom */
rc = bnx2_nvram_read(bp, eeprom->offset, eebuf, eeprom->len);
@@ -4816,11 +4814,7 @@ bnx2_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
struct bnx2 *bp = dev->priv;
int rc;
- if (eeprom->offset > bp->flash_info->total_size)
- return -EINVAL;
-
- if ((eeprom->offset + eeprom->len) > bp->flash_info->total_size)
- eeprom->len = bp->flash_info->total_size - eeprom->offset;
+ /* parameters already validated in ethtool_set_eeprom */
rc = bnx2_nvram_write(bp, eeprom->offset, eebuf, eeprom->len);
diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c
index 9342d5bc7bb4..f5d49a110654 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -37,6 +37,7 @@
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/fs.h>
+#include <linux/platform_device.h>
#include <linux/vmalloc.h>
#include <asm/pgtable.h>
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index a940b96433c7..e67b1d06611c 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -34,6 +34,7 @@
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/fs.h>
+#include <linux/platform_device.h>
#include <asm/immap_cpm2.h>
#include <asm/mpc8260.h>
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 5ef4e845a387..2e8f44469699 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -34,6 +34,7 @@
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/fs.h>
+#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c
index d8c6e9cadcf5..a3897fda71fa 100644
--- a/drivers/net/fs_enet/mac-scc.c
+++ b/drivers/net/fs_enet/mac-scc.c
@@ -34,6 +34,7 @@
#include <linux/ethtool.h>
#include <linux/bitops.h>
#include <linux/fs.h>
+#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index c796f41b4a52..0d765f1733b5 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -2290,7 +2290,6 @@ spider_net_remove(struct pci_dev *pdev)
}
static struct pci_driver spider_net_driver = {
- .owner = THIS_MODULE,
.name = spider_net_driver_name,
.id_table = spider_net_pci_tbl,
.probe = spider_net_probe,
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index 2a42add7f563..ea16805a153c 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -2,6 +2,8 @@
#include <linux/module.h>
#include <linux/ioport.h>
+#include "pci.h"
+
/*
* This interrupt-safe spinlock protects all accesses to PCI
* configuration space.
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 061ead21ef14..c42b68d3aa24 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -32,8 +32,6 @@
#include <linux/types.h>
#include <linux/pci.h>
#include <linux/delay.h>
-#include <asm/semaphore.h>
-#include <asm/io.h>
#include <linux/pcieport_if.h>
#include "pci_hotplug.h"
@@ -42,6 +40,7 @@
extern int pciehp_poll_mode;
extern int pciehp_poll_time;
extern int pciehp_debug;
+extern int pciehp_force;
/*#define dbg(format, arg...) do { if (pciehp_debug) printk(KERN_DEBUG "%s: " format, MY_NAME , ## arg); } while (0)*/
#define dbg(format, arg...) do { if (pciehp_debug) printk("%s: " format, MY_NAME , ## arg); } while (0)
@@ -49,39 +48,20 @@ extern int pciehp_debug;
#define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
-struct pci_func {
- struct pci_func *next;
- u8 bus;
- u8 device;
- u8 function;
- u8 is_a_board;
- u16 status;
- u8 configured;
- u8 switch_save;
- u8 presence_save;
- u32 base_length[0x06];
- u8 base_type[0x06];
- u16 reserved2;
- u32 config_space[0x20];
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
- struct pci_dev* pci_dev;
+struct hotplug_params {
+ u8 cache_line_size;
+ u8 latency_timer;
+ u8 enable_serr;
+ u8 enable_perr;
};
struct slot {
struct slot *next;
u8 bus;
u8 device;
+ u16 status;
u32 number;
- u8 is_a_board;
- u8 configured;
u8 state;
- u8 switch_save;
- u8 presence_save;
- u32 capabilities;
- u16 reserved2;
struct timer_list task_event;
u8 hp_slot;
struct controller *ctrl;
@@ -90,42 +70,47 @@ struct slot {
struct list_head slot_list;
};
-struct pci_resource {
- struct pci_resource * next;
- u32 base;
- u32 length;
-};
-
struct event_info {
u32 event_type;
u8 hp_slot;
};
+typedef u8(*php_intr_callback_t) (u8 hp_slot, void *instance_id);
+
+struct php_ctlr_state_s {
+ struct php_ctlr_state_s *pnext;
+ struct pci_dev *pci_dev;
+ unsigned int irq;
+ unsigned long flags; /* spinlock's */
+ u32 slot_device_offset;
+ u32 num_slots;
+ struct timer_list int_poll_timer; /* Added for poll event */
+ php_intr_callback_t attention_button_callback;
+ php_intr_callback_t switch_change_callback;
+ php_intr_callback_t presence_change_callback;
+ php_intr_callback_t power_fault_callback;
+ void *callback_instance_id;
+ struct ctrl_reg *creg; /* Ptr to controller register space */
+};
+
+#define MAX_EVENTS 10
struct controller {
struct controller *next;
struct semaphore crit_sect; /* critical section semaphore */
- void *hpc_ctlr_handle; /* HPC controller handle */
+ struct php_ctlr_state_s *hpc_ctlr_handle; /* HPC controller handle */
int num_slots; /* Number of slots on ctlr */
int slot_num_inc; /* 1 or -1 */
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
struct pci_dev *pci_dev;
struct pci_bus *pci_bus;
- struct event_info event_queue[10];
+ struct event_info event_queue[MAX_EVENTS];
struct slot *slot;
struct hpc_ops *hpc_ops;
wait_queue_head_t queue; /* sleep & wake process */
u8 next_event;
- u8 seg;
u8 bus;
u8 device;
u8 function;
- u8 rev;
u8 slot_device_offset;
- u8 add_support;
- enum pci_bus_speed speed;
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 ctrlcap;
@@ -133,20 +118,6 @@ struct controller {
u8 cap_base;
};
-struct irq_mapping {
- u8 barber_pole;
- u8 valid_INT;
- u8 interrupt[4];
-};
-
-struct resource_lists {
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
- struct irq_mapping *irqs;
-};
-
#define INT_BUTTON_IGNORE 0
#define INT_PRESENCE_ON 1
#define INT_PRESENCE_OFF 2
@@ -200,21 +171,14 @@ struct resource_lists {
* error Messages
*/
#define msg_initialization_err "Initialization failure, error=%d\n"
-#define msg_HPC_rev_error "Unsupported revision of the PCI hot plug controller found.\n"
-#define msg_HPC_non_pcie "The PCI hot plug controller is not supported by this driver.\n"
-#define msg_HPC_not_supported "This system is not supported by this version of pciephd module. Upgrade to a newer version of pciehpd\n"
-#define msg_unable_to_save "Unable to store PCI hot plug add resource information. This system must be rebooted before adding any PCI devices.\n"
#define msg_button_on "PCI slot #%d - powering on due to button press.\n"
#define msg_button_off "PCI slot #%d - powering off due to button press.\n"
#define msg_button_cancel "PCI slot #%d - action canceled due to button press.\n"
#define msg_button_ignore "PCI slot #%d - button press ignored. (action in progress...)\n"
/* controller functions */
-extern int pciehprm_find_available_resources (struct controller *ctrl);
extern int pciehp_event_start_thread (void);
extern void pciehp_event_stop_thread (void);
-extern struct pci_func *pciehp_slot_create (unsigned char busnumber);
-extern struct pci_func *pciehp_slot_find (unsigned char bus, unsigned char device, unsigned char index);
extern int pciehp_enable_slot (struct slot *slot);
extern int pciehp_disable_slot (struct slot *slot);
@@ -224,25 +188,17 @@ extern u8 pciehp_handle_presence_change (u8 hp_slot, void *inst_id);
extern u8 pciehp_handle_power_fault (u8 hp_slot, void *inst_id);
/* extern void long_delay (int delay); */
-/* resource functions */
-extern int pciehp_resource_sort_and_combine (struct pci_resource **head);
-
/* pci functions */
-extern int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num);
-/*extern int pciehp_get_bus_dev (struct controller *ctrl, u8 *bus_num, u8 *dev_num, struct slot *slot);*/
-extern int pciehp_save_config (struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num);
-extern int pciehp_save_used_resources (struct controller *ctrl, struct pci_func * func, int flag);
-extern int pciehp_save_slot_config (struct controller *ctrl, struct pci_func * new_slot);
-extern void pciehp_destroy_board_resources (struct pci_func * func);
-extern int pciehp_return_board_resources (struct pci_func * func, struct resource_lists * resources);
-extern void pciehp_destroy_resource_list (struct resource_lists * resources);
-extern int pciehp_configure_device (struct controller* ctrl, struct pci_func* func);
-extern int pciehp_unconfigure_device (struct pci_func* func);
+extern int pciehp_configure_device (struct slot *p_slot);
+extern int pciehp_unconfigure_device (struct slot *p_slot);
+extern int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev);
+extern void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp);
+
/* Global variables */
extern struct controller *pciehp_ctrl_list;
-extern struct pci_func *pciehp_slot_list[256];
/* Inline functions */
@@ -252,12 +208,9 @@ static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
p_slot = ctrl->slot;
- dbg("p_slot = %p\n", p_slot);
-
while (p_slot && (p_slot->device != device)) {
tmp_slot = p_slot;
p_slot = p_slot->next;
- dbg("In while loop, p_slot = %p\n", p_slot);
}
if (p_slot == NULL) {
err("ERROR: pciehp_find_slot device=0x%x\n", device);
@@ -273,7 +226,6 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
DECLARE_WAITQUEUE(wait, current);
- dbg("%s : start\n", __FUNCTION__);
add_wait_queue(&ctrl->queue, &wait);
if (!pciehp_poll_mode)
/* Sleep for up to 1 second */
@@ -285,19 +237,9 @@ static inline int wait_for_ctrl_irq(struct controller *ctrl)
if (signal_pending(current))
retval = -EINTR;
- dbg("%s : end\n", __FUNCTION__);
return retval;
}
-/* Puts node back in the resource list pointed to by head */
-static inline void return_resource(struct pci_resource **head, struct pci_resource *node)
-{
- if (!node || !head)
- return;
- node->next = *head;
- *head = node;
-}
-
#define SLOT_NAME_SIZE 10
static inline void make_slot_name(char *buffer, int buffer_size, struct slot *slot)
@@ -311,14 +253,7 @@ enum php_ctlr_type {
ACPI
};
-typedef u8(*php_intr_callback_t) (unsigned int change_id, void *instance_id);
-
-int pcie_init(struct controller *ctrl, struct pcie_device *dev,
- php_intr_callback_t attention_button_callback,
- php_intr_callback_t switch_change_callback,
- php_intr_callback_t presence_change_callback,
- php_intr_callback_t power_fault_callback);
-
+int pcie_init(struct controller *ctrl, struct pcie_device *dev);
/* This has no meaning for PCI Express, as there is only 1 slot per port */
int pcie_get_ctlr_slot_config(struct controller *ctrl,
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index cafc7eadcf80..8df704860348 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -27,27 +27,20 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
#include <linux/pci.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
#include "pciehp.h"
-#include "pciehprm.h"
#include <linux/interrupt.h>
/* Global variables */
int pciehp_debug;
int pciehp_poll_mode;
int pciehp_poll_time;
+int pciehp_force;
struct controller *pciehp_ctrl_list;
-struct pci_func *pciehp_slot_list[256];
#define DRIVER_VERSION "0.4"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -60,9 +53,11 @@ MODULE_LICENSE("GPL");
module_param(pciehp_debug, bool, 0644);
module_param(pciehp_poll_mode, bool, 0644);
module_param(pciehp_poll_time, int, 0644);
+module_param(pciehp_force, bool, 0644);
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_time, "Polling mechanism frequency, in seconds");
+MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing");
#define PCIE_MODULE_NAME "pciehp"
@@ -114,8 +109,6 @@ static int init_slots(struct controller *ctrl)
u32 slot_number;
int result = -ENOMEM;
- dbg("%s\n",__FUNCTION__);
-
number_of_slots = ctrl->num_slots;
slot_device = ctrl->slot_device_offset;
slot_number = ctrl->first_slot;
@@ -370,7 +363,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
u8 value;
struct pci_dev *pdev;
- dbg("%s: Called by hp_drv\n", __FUNCTION__);
ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL);
if (!ctrl) {
err("%s : out of memory\n", __FUNCTION__);
@@ -378,22 +370,15 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
}
memset(ctrl, 0, sizeof(struct controller));
- dbg("%s: DRV_thread pid = %d\n", __FUNCTION__, current->pid);
-
pdev = dev->port;
+ ctrl->pci_dev = pdev;
- rc = pcie_init(ctrl, dev,
- (php_intr_callback_t) pciehp_handle_attention_button,
- (php_intr_callback_t) pciehp_handle_switch_change,
- (php_intr_callback_t) pciehp_handle_presence_change,
- (php_intr_callback_t) pciehp_handle_power_fault);
+ rc = pcie_init(ctrl, dev);
if (rc) {
dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
goto err_out_free_ctrl;
}
- ctrl->pci_dev = pdev;
-
pci_set_drvdata(pdev, ctrl);
ctrl->pci_bus = kmalloc(sizeof(*ctrl->pci_bus), GFP_KERNEL);
@@ -402,7 +387,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
rc = -ENOMEM;
goto err_out_unmap_mmio_region;
}
- dbg("%s: ctrl->pci_bus %p\n", __FUNCTION__, ctrl->pci_bus);
memcpy (ctrl->pci_bus, pdev->bus, sizeof (*ctrl->pci_bus));
ctrl->bus = pdev->bus->number; /* ctrl bus */
ctrl->slot_bus = pdev->subordinate->number; /* bus controlled by this HPC */
@@ -424,25 +408,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
first_device_num = ctrl->slot_device_offset;
num_ctlr_slots = ctrl->num_slots;
- /* Store PCI Config Space for all devices on this bus */
- dbg("%s: Before calling pciehp_save_config, ctrl->bus %x,ctrl->slot_bus %x\n",
- __FUNCTION__,ctrl->bus, ctrl->slot_bus);
- rc = pciehp_save_config(ctrl, ctrl->slot_bus, num_ctlr_slots, first_device_num);
- if (rc) {
- err("%s: unable to save PCI configuration data, error %d\n", __FUNCTION__, rc);
- goto err_out_free_ctrl_bus;
- }
-
- /* Get IO, memory, and IRQ resources for new devices */
- rc = pciehprm_find_available_resources(ctrl);
- ctrl->add_support = !rc;
-
- if (rc) {
- dbg("pciehprm_find_available_resources = %#x\n", rc);
- err("unable to locate PCI configuration resources for hot plug add.\n");
- goto err_out_free_ctrl_bus;
- }
-
/* Setup the slot information structures */
rc = init_slots(ctrl);
if (rc) {
@@ -451,7 +416,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
}
t_slot = pciehp_find_slot(ctrl, first_device_num);
- dbg("%s: t_slot %p\n", __FUNCTION__, t_slot);
/* Finish setting up the hot plug ctrl device */
ctrl->next_event = 0;
@@ -468,7 +432,6 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
down(&ctrl->crit_sect);
t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */
- dbg("%s: adpater value %x\n", __FUNCTION__, value);
if ((POWER_CTRL(ctrl->ctrlcap)) && !value) {
rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/
@@ -501,7 +464,6 @@ err_out_none:
static int pcie_start_thread(void)
{
- int loop;
int retval = 0;
dbg("Initialize + Start the notification/polling mechanism \n");
@@ -512,32 +474,11 @@ static int pcie_start_thread(void)
return retval;
}
- dbg("Initialize slot lists\n");
- /* One slot list for each bus in the system */
- for (loop = 0; loop < 256; loop++) {
- pciehp_slot_list[loop] = NULL;
- }
-
return retval;
}
-static inline void __exit
-free_pciehp_res(struct pci_resource *res)
-{
- struct pci_resource *tres;
-
- while (res) {
- tres = res;
- res = res->next;
- kfree(tres);
- }
-}
-
static void __exit unload_pciehpd(void)
{
- struct pci_func *next;
- struct pci_func *TempSlot;
- int loop;
struct controller *ctrl;
struct controller *tctrl;
@@ -546,11 +487,6 @@ static void __exit unload_pciehpd(void)
while (ctrl) {
cleanup_slots(ctrl);
- free_pciehp_res(ctrl->io_head);
- free_pciehp_res(ctrl->mem_head);
- free_pciehp_res(ctrl->p_mem_head);
- free_pciehp_res(ctrl->bus_head);
-
kfree (ctrl->pci_bus);
ctrl->hpc_ops->release_ctlr(ctrl);
@@ -561,20 +497,6 @@ static void __exit unload_pciehpd(void)
kfree(tctrl);
}
- for (loop = 0; loop < 256; loop++) {
- next = pciehp_slot_list[loop];
- while (next != NULL) {
- free_pciehp_res(next->io_head);
- free_pciehp_res(next->mem_head);
- free_pciehp_res(next->p_mem_head);
- free_pciehp_res(next->bus_head);
-
- TempSlot = next;
- next = next->next;
- kfree(TempSlot);
- }
- }
-
/* Stop the notification mechanism */
pciehp_event_stop_thread();
@@ -639,21 +561,16 @@ static int __init pcied_init(void)
if (retval)
goto error_hpc_init;
- retval = pciehprm_init(PCI);
- if (!retval) {
- retval = pcie_port_service_register(&hpdriver_portdrv);
- dbg("pcie_port_service_register = %d\n", retval);
- info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- if (retval)
- dbg("%s: Failure to register service\n", __FUNCTION__);
- }
+ retval = pcie_port_service_register(&hpdriver_portdrv);
+ dbg("pcie_port_service_register = %d\n", retval);
+ info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
+ if (retval)
+ dbg("%s: Failure to register service\n", __FUNCTION__);
error_hpc_init:
if (retval) {
- pciehprm_cleanup();
pciehp_event_stop_thread();
- } else
- pciehprm_print_pirt();
+ };
return retval;
}
@@ -663,9 +580,6 @@ static void __exit pcied_cleanup(void)
dbg("unload_pciehpd()\n");
unload_pciehpd();
- pciehprm_cleanup();
-
- dbg("pcie_port_service_unregister\n");
pcie_port_service_unregister(&hpdriver_portdrv);
info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 898f6da6f0de..5e582eca21d8 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -27,25 +27,14 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
#include <linux/smp_lock.h>
#include <linux/pci.h>
#include "../pci.h"
#include "pciehp.h"
-#include "pciehprm.h"
-static u32 configure_new_device(struct controller *ctrl, struct pci_func *func,
- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
-static int configure_new_function( struct controller *ctrl, struct pci_func *func,
- u8 behind_bridge, struct resource_lists *resources, u8 bridge_bus, u8 bridge_dev);
static void interrupt_event_handler(struct controller *ctrl);
static struct semaphore event_semaphore; /* mutex for process loop (up if something to process) */
@@ -60,22 +49,18 @@ u8 pciehp_handle_attention_button(u8 hp_slot, void *inst_id)
struct slot *p_slot;
u8 rc = 0;
u8 getstatus;
- struct pci_func *func;
struct event_info *taskInfo;
/* Attention Button Change */
dbg("pciehp: Attention button interrupt received.\n");
- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread what to do */
taskInfo = &(ctrl->event_queue[ctrl->next_event]);
p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
- ctrl->next_event = (ctrl->next_event + 1) % 10;
+ ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
taskInfo->hp_slot = hp_slot;
rc++;
@@ -117,24 +102,20 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
struct slot *p_slot;
u8 rc = 0;
u8 getstatus;
- struct pci_func *func;
struct event_info *taskInfo;
/* Switch Change */
dbg("pciehp: Switch interrupt received.\n");
- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread
* what to do
*/
taskInfo = &(ctrl->event_queue[ctrl->next_event]);
- ctrl->next_event = (ctrl->next_event + 1) % 10;
+ ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
taskInfo->hp_slot = hp_slot;
rc++;
p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
if (getstatus) {
@@ -142,14 +123,12 @@ u8 pciehp_handle_switch_change(u8 hp_slot, void *inst_id)
* Switch opened
*/
info("Latch open on Slot(%d)\n", ctrl->first_slot + hp_slot);
- func->switch_save = 0;
taskInfo->event_type = INT_SWITCH_OPEN;
} else {
/*
* Switch closed
*/
info("Latch close on Slot(%d)\n", ctrl->first_slot + hp_slot);
- func->switch_save = 0x10;
taskInfo->event_type = INT_SWITCH_CLOSE;
}
@@ -163,20 +142,17 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id)
{
struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
- u8 rc = 0;
- struct pci_func *func;
+ u8 presence_save, rc = 0;
struct event_info *taskInfo;
/* Presence Change */
dbg("pciehp: Presence/Notify input change.\n");
- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* This is the structure that tells the worker thread
* what to do
*/
taskInfo = &(ctrl->event_queue[ctrl->next_event]);
- ctrl->next_event = (ctrl->next_event + 1) % 10;
+ ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
taskInfo->hp_slot = hp_slot;
rc++;
@@ -185,8 +161,8 @@ u8 pciehp_handle_presence_change(u8 hp_slot, void *inst_id)
/* Switch is open, assume a presence change
* Save the presence state
*/
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
- if (func->presence_save) {
+ p_slot->hpc_ops->get_adapter_status(p_slot, &presence_save);
+ if (presence_save) {
/*
* Card Present
*/
@@ -211,19 +187,16 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
struct controller *ctrl = (struct controller *) inst_id;
struct slot *p_slot;
u8 rc = 0;
- struct pci_func *func;
struct event_info *taskInfo;
/* power fault */
dbg("pciehp: Power fault interrupt received.\n");
- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
/* this is the structure that tells the worker thread
* what to do
*/
taskInfo = &(ctrl->event_queue[ctrl->next_event]);
- ctrl->next_event = (ctrl->next_event + 1) % 10;
+ ctrl->next_event = (ctrl->next_event + 1) % MAX_EVENTS;
taskInfo->hp_slot = hp_slot;
rc++;
@@ -234,7 +207,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
* power fault Cleared
*/
info("Power fault cleared on Slot(%d)\n", ctrl->first_slot + hp_slot);
- func->status = 0x00;
+ p_slot->status = 0x00;
taskInfo->event_type = INT_POWER_FAULT_CLEAR;
} else {
/*
@@ -243,7 +216,7 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
info("Power fault on Slot(%d)\n", ctrl->first_slot + hp_slot);
taskInfo->event_type = INT_POWER_FAULT;
/* set power fault status for this board */
- func->status = 0xFF;
+ p_slot->status = 0xFF;
info("power fault bit %x set\n", hp_slot);
}
if (rc)
@@ -252,810 +225,6 @@ u8 pciehp_handle_power_fault(u8 hp_slot, void *inst_id)
return rc;
}
-
-/**
- * sort_by_size: sort nodes by their length, smallest first.
- *
- * @head: list to sort
- */
-static int sort_by_size(struct pci_resource **head)
-{
- struct pci_resource *current_res;
- struct pci_resource *next_res;
- int out_of_order = 1;
-
- if (!(*head))
- return 1;
-
- if (!((*head)->next))
- return 0;
-
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->length > (*head)->next->length)) {
- out_of_order++;
- current_res = *head;
- *head = (*head)->next;
- current_res->next = (*head)->next;
- (*head)->next = current_res;
- }
-
- current_res = *head;
-
- while (current_res->next && current_res->next->next) {
- if (current_res->next->length > current_res->next->next->length) {
- out_of_order++;
- next_res = current_res->next;
- current_res->next = current_res->next->next;
- current_res = current_res->next;
- next_res->next = current_res->next;
- current_res->next = next_res;
- } else
- current_res = current_res->next;
- }
- } /* End of out_of_order loop */
-
- return 0;
-}
-
-
-/*
- * sort_by_max_size
- *
- * Sorts nodes on the list by their length.
- * Largest first.
- *
- */
-static int sort_by_max_size(struct pci_resource **head)
-{
- struct pci_resource *current_res;
- struct pci_resource *next_res;
- int out_of_order = 1;
-
- if (!(*head))
- return 1;
-
- if (!((*head)->next))
- return 0;
-
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->length < (*head)->next->length)) {
- out_of_order++;
- current_res = *head;
- *head = (*head)->next;
- current_res->next = (*head)->next;
- (*head)->next = current_res;
- }
-
- current_res = *head;
-
- while (current_res->next && current_res->next->next) {
- if (current_res->next->length < current_res->next->next->length) {
- out_of_order++;
- next_res = current_res->next;
- current_res->next = current_res->next->next;
- current_res = current_res->next;
- next_res->next = current_res->next;
- current_res->next = next_res;
- } else
- current_res = current_res->next;
- }
- } /* End of out_of_order loop */
-
- return 0;
-}
-
-
-/**
- * do_pre_bridge_resource_split: return one unused resource node
- * @head: list to scan
- *
- */
-static struct pci_resource *
-do_pre_bridge_resource_split(struct pci_resource **head,
- struct pci_resource **orig_head, u32 alignment)
-{
- struct pci_resource *prevnode = NULL;
- struct pci_resource *node;
- struct pci_resource *split_node;
- u32 rc;
- u32 temp_dword;
- dbg("do_pre_bridge_resource_split\n");
-
- if (!(*head) || !(*orig_head))
- return NULL;
-
- rc = pciehp_resource_sort_and_combine(head);
-
- if (rc)
- return NULL;
-
- if ((*head)->base != (*orig_head)->base)
- return NULL;
-
- if ((*head)->length == (*orig_head)->length)
- return NULL;
-
-
- /* If we got here, there the bridge requires some of the resource, but
- * we may be able to split some off of the front
- */
- node = *head;
-
- if (node->length & (alignment -1)) {
- /* this one isn't an aligned length, so we'll make a new entry
- * and split it up.
- */
- split_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-
- if (!split_node)
- return NULL;
-
- temp_dword = (node->length | (alignment-1)) + 1 - alignment;
-
- split_node->base = node->base;
- split_node->length = temp_dword;
-
- node->length -= temp_dword;
- node->base += split_node->length;
-
- /* Put it in the list */
- *head = split_node;
- split_node->next = node;
- }
-
- if (node->length < alignment)
- return NULL;
-
- /* Now unlink it */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
-
- return node;
-}
-
-
-/**
- * do_bridge_resource_split: return one unused resource node
- * @head: list to scan
- *
- */
-static struct pci_resource *
-do_bridge_resource_split(struct pci_resource **head, u32 alignment)
-{
- struct pci_resource *prevnode = NULL;
- struct pci_resource *node;
- u32 rc;
- u32 temp_dword;
-
- if (!(*head))
- return NULL;
-
- rc = pciehp_resource_sort_and_combine(head);
-
- if (rc)
- return NULL;
-
- node = *head;
-
- while (node->next) {
- prevnode = node;
- node = node->next;
- kfree(prevnode);
- }
-
- if (node->length < alignment) {
- kfree(node);
- return NULL;
- }
-
- if (node->base & (alignment - 1)) {
- /* Short circuit if adjusted size is too small */
- temp_dword = (node->base | (alignment-1)) + 1;
- if ((node->length - (temp_dword - node->base)) < alignment) {
- kfree(node);
- return NULL;
- }
-
- node->length -= (temp_dword - node->base);
- node->base = temp_dword;
- }
-
- if (node->length & (alignment - 1)) {
- /* There's stuff in use after this node */
- kfree(node);
- return NULL;
- }
-
- return node;
-}
-
-
-/*
- * get_io_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length that is not in the
- * ISA aliasing window. If it finds a node larger than "size"
- * it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_io_resource(struct pci_resource **head, u32 size)
-{
- struct pci_resource *prevnode;
- struct pci_resource *node;
- struct pci_resource *split_node = NULL;
- u32 temp_dword;
-
- if (!(*head))
- return NULL;
-
- if ( pciehp_resource_sort_and_combine(head) )
- return NULL;
-
- if ( sort_by_size(head) )
- return NULL;
-
- for (node = *head; node; node = node->next) {
- if (node->length < size)
- continue;
-
- if (node->base & (size - 1)) {
- /* this one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_dword = (node->base | (size-1)) + 1;
-
- /*/ Short circuit if adjusted size is too small */
- if ((node->length - (temp_dword - node->base)) < size)
- continue;
-
- split_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
-
- if (!split_node)
- return NULL;
-
- split_node->base = node->base;
- split_node->length = temp_dword - node->base;
- node->base = temp_dword;
- node->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of non-aligned base */
-
- /* Don't need to check if too small since we already did */
- if (node->length > size) {
- /* this one is longer than we need
- so we'll make a new entry and split it up */
- split_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
-
- if (!split_node)
- return NULL;
-
- split_node->base = node->base + size;
- split_node->length = node->length - size;
- node->length = size;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of too big on top end */
-
- /* For IO make sure it's not in the ISA aliasing space */
- if (node->base & 0x300L)
- continue;
-
- /* If we got here, then it is the right size
- Now take it out of the list */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
- /* Stop looping */
- break;
- }
-
- return node;
-}
-
-
-/*
- * get_max_resource
- *
- * Gets the largest node that is at least "size" big from the
- * list pointed to by head. It aligns the node on top and bottom
- * to "size" alignment before returning it.
- * J.I. modified to put max size limits of; 64M->32M->16M->8M->4M->1M
- * This is needed to avoid allocating entire ACPI _CRS res to one child bridge/slot.
- */
-static struct pci_resource *get_max_resource(struct pci_resource **head, u32 size)
-{
- struct pci_resource *max;
- struct pci_resource *temp;
- struct pci_resource *split_node;
- u32 temp_dword;
- u32 max_size[] = { 0x4000000, 0x2000000, 0x1000000, 0x0800000, 0x0400000, 0x0200000, 0x0100000, 0x00 };
- int i;
-
- if (!(*head))
- return NULL;
-
- if (pciehp_resource_sort_and_combine(head))
- return NULL;
-
- if (sort_by_max_size(head))
- return NULL;
-
- for (max = *head;max; max = max->next) {
-
- /* If not big enough we could probably just bail,
- instead we'll continue to the next. */
- if (max->length < size)
- continue;
-
- if (max->base & (size - 1)) {
- /* this one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_dword = (max->base | (size-1)) + 1;
-
- /* Short circuit if adjusted size is too small */
- if ((max->length - (temp_dword - max->base)) < size)
- continue;
-
- split_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
-
- if (!split_node)
- return NULL;
-
- split_node->base = max->base;
- split_node->length = temp_dword - max->base;
- max->base = temp_dword;
- max->length -= split_node->length;
-
- /* Put it next in the list */
- split_node->next = max->next;
- max->next = split_node;
- }
-
- if ((max->base + max->length) & (size - 1)) {
- /* this one isn't end aligned properly at the top
- so we'll make a new entry and split it up */
- split_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
-
- if (!split_node)
- return NULL;
- temp_dword = ((max->base + max->length) & ~(size - 1));
- split_node->base = temp_dword;
- split_node->length = max->length + max->base
- - split_node->base;
- max->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = max->next;
- max->next = split_node;
- }
-
- /* Make sure it didn't shrink too much when we aligned it */
- if (max->length < size)
- continue;
-
- for ( i = 0; max_size[i] > size; i++) {
- if (max->length > max_size[i]) {
- split_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!split_node)
- break; /* return NULL; */
- split_node->base = max->base + max_size[i];
- split_node->length = max->length - max_size[i];
- max->length = max_size[i];
- /* Put it next in the list */
- split_node->next = max->next;
- max->next = split_node;
- break;
- }
- }
-
- /* Now take it out of the list */
- temp = (struct pci_resource*) *head;
- if (temp == max) {
- *head = max->next;
- } else {
- while (temp && temp->next != max) {
- temp = temp->next;
- }
-
- temp->next = max->next;
- }
-
- max->next = NULL;
- return max;
- }
-
- /* If we get here, we couldn't find one */
- return NULL;
-}
-
-
-/*
- * get_resource
- *
- * this function sorts the resource list by size and then
- * returns the first node of "size" length. If it finds a node
- * larger than "size" it will split it up.
- *
- * size must be a power of two.
- */
-static struct pci_resource *get_resource(struct pci_resource **head, u32 size)
-{
- struct pci_resource *prevnode;
- struct pci_resource *node;
- struct pci_resource *split_node;
- u32 temp_dword;
-
- if (!(*head))
- return NULL;
-
- if ( pciehp_resource_sort_and_combine(head) )
- return NULL;
-
- if ( sort_by_size(head) )
- return NULL;
-
- for (node = *head; node; node = node->next) {
- dbg("%s: req_size =0x%x node=%p, base=0x%x, length=0x%x\n",
- __FUNCTION__, size, node, node->base, node->length);
- if (node->length < size)
- continue;
-
- if (node->base & (size - 1)) {
- dbg("%s: not aligned\n", __FUNCTION__);
- /* this one isn't base aligned properly
- so we'll make a new entry and split it up */
- temp_dword = (node->base | (size-1)) + 1;
-
- /* Short circuit if adjusted size is too small */
- if ((node->length - (temp_dword - node->base)) < size)
- continue;
-
- split_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
-
- if (!split_node)
- return NULL;
-
- split_node->base = node->base;
- split_node->length = temp_dword - node->base;
- node->base = temp_dword;
- node->length -= split_node->length;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of non-aligned base */
-
- /* Don't need to check if too small since we already did */
- if (node->length > size) {
- dbg("%s: too big\n", __FUNCTION__);
- /* this one is longer than we need
- so we'll make a new entry and split it up */
- split_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
-
- if (!split_node)
- return NULL;
-
- split_node->base = node->base + size;
- split_node->length = node->length - size;
- node->length = size;
-
- /* Put it in the list */
- split_node->next = node->next;
- node->next = split_node;
- } /* End of too big on top end */
-
- dbg("%s: got one!!!\n", __FUNCTION__);
- /* If we got here, then it is the right size
- Now take it out of the list */
- if (*head == node) {
- *head = node->next;
- } else {
- prevnode = *head;
- while (prevnode->next != node)
- prevnode = prevnode->next;
-
- prevnode->next = node->next;
- }
- node->next = NULL;
- /* Stop looping */
- break;
- }
- return node;
-}
-
-
-/*
- * pciehp_resource_sort_and_combine
- *
- * Sorts all of the nodes in the list in ascending order by
- * their base addresses. Also does garbage collection by
- * combining adjacent nodes.
- *
- * returns 0 if success
- */
-int pciehp_resource_sort_and_combine(struct pci_resource **head)
-{
- struct pci_resource *node1;
- struct pci_resource *node2;
- int out_of_order = 1;
-
- dbg("%s: head = %p, *head = %p\n", __FUNCTION__, head, *head);
-
- if (!(*head))
- return 1;
-
- dbg("*head->next = %p\n",(*head)->next);
-
- if (!(*head)->next)
- return 0; /* only one item on the list, already sorted! */
-
- dbg("*head->base = 0x%x\n",(*head)->base);
- dbg("*head->next->base = 0x%x\n",(*head)->next->base);
- while (out_of_order) {
- out_of_order = 0;
-
- /* Special case for swapping list head */
- if (((*head)->next) &&
- ((*head)->base > (*head)->next->base)) {
- node1 = *head;
- (*head) = (*head)->next;
- node1->next = (*head)->next;
- (*head)->next = node1;
- out_of_order++;
- }
-
- node1 = (*head);
-
- while (node1->next && node1->next->next) {
- if (node1->next->base > node1->next->next->base) {
- out_of_order++;
- node2 = node1->next;
- node1->next = node1->next->next;
- node1 = node1->next;
- node2->next = node1->next;
- node1->next = node2;
- } else
- node1 = node1->next;
- }
- } /* End of out_of_order loop */
-
- node1 = *head;
-
- while (node1 && node1->next) {
- if ((node1->base + node1->length) == node1->next->base) {
- /* Combine */
- dbg("8..\n");
- node1->length += node1->next->length;
- node2 = node1->next;
- node1->next = node1->next->next;
- kfree(node2);
- } else
- node1 = node1->next;
- }
-
- return 0;
-}
-
-
-/**
- * pciehp_slot_create - Creates a node and adds it to the proper bus.
- * @busnumber - bus where new node is to be located
- *
- * Returns pointer to the new node or NULL if unsuccessful
- */
-struct pci_func *pciehp_slot_create(u8 busnumber)
-{
- struct pci_func *new_slot;
- struct pci_func *next;
- dbg("%s: busnumber %x\n", __FUNCTION__, busnumber);
- new_slot = kmalloc(sizeof(struct pci_func), GFP_KERNEL);
-
- if (new_slot == NULL)
- return new_slot;
-
- memset(new_slot, 0, sizeof(struct pci_func));
-
- new_slot->next = NULL;
- new_slot->configured = 1;
-
- if (pciehp_slot_list[busnumber] == NULL) {
- pciehp_slot_list[busnumber] = new_slot;
- } else {
- next = pciehp_slot_list[busnumber];
- while (next->next != NULL)
- next = next->next;
- next->next = new_slot;
- }
- return new_slot;
-}
-
-
-/**
- * slot_remove - Removes a node from the linked list of slots.
- * @old_slot: slot to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int slot_remove(struct pci_func * old_slot)
-{
- struct pci_func *next;
-
- if (old_slot == NULL)
- return 1;
-
- next = pciehp_slot_list[old_slot->bus];
-
- if (next == NULL)
- return 1;
-
- if (next == old_slot) {
- pciehp_slot_list[old_slot->bus] = old_slot->next;
- pciehp_destroy_board_resources(old_slot);
- kfree(old_slot);
- return 0;
- }
-
- while ((next->next != old_slot) && (next->next != NULL)) {
- next = next->next;
- }
-
- if (next->next == old_slot) {
- next->next = old_slot->next;
- pciehp_destroy_board_resources(old_slot);
- kfree(old_slot);
- return 0;
- } else
- return 2;
-}
-
-
-/**
- * bridge_slot_remove - Removes a node from the linked list of slots.
- * @bridge: bridge to remove
- *
- * Returns 0 if successful, !0 otherwise.
- */
-static int bridge_slot_remove(struct pci_func *bridge)
-{
- u8 subordinateBus, secondaryBus;
- u8 tempBus;
- struct pci_func *next;
-
- if (bridge == NULL)
- return 1;
-
- secondaryBus = (bridge->config_space[0x06] >> 8) & 0xFF;
- subordinateBus = (bridge->config_space[0x06] >> 16) & 0xFF;
-
- for (tempBus = secondaryBus; tempBus <= subordinateBus; tempBus++) {
- next = pciehp_slot_list[tempBus];
-
- while (!slot_remove(next)) {
- next = pciehp_slot_list[tempBus];
- }
- }
-
- next = pciehp_slot_list[bridge->bus];
-
- if (next == NULL) {
- return 1;
- }
-
- if (next == bridge) {
- pciehp_slot_list[bridge->bus] = bridge->next;
- kfree(bridge);
- return 0;
- }
-
- while ((next->next != bridge) && (next->next != NULL)) {
- next = next->next;
- }
-
- if (next->next == bridge) {
- next->next = bridge->next;
- kfree(bridge);
- return 0;
- } else
- return 2;
-}
-
-
-/**
- * pciehp_slot_find - Looks for a node by bus, and device, multiple functions accessed
- * @bus: bus to find
- * @device: device to find
- * @index: is 0 for first function found, 1 for the second...
- *
- * Returns pointer to the node if successful, %NULL otherwise.
- */
-struct pci_func *pciehp_slot_find(u8 bus, u8 device, u8 index)
-{
- int found = -1;
- struct pci_func *func;
-
- func = pciehp_slot_list[bus];
- dbg("%s: bus %x device %x index %x\n",
- __FUNCTION__, bus, device, index);
- if (func != NULL) {
- dbg("%s: func-> bus %x device %x function %x pci_dev %p\n",
- __FUNCTION__, func->bus, func->device, func->function,
- func->pci_dev);
- } else
- dbg("%s: func == NULL\n", __FUNCTION__);
-
- if ((func == NULL) || ((func->device == device) && (index == 0)))
- return func;
-
- if (func->device == device)
- found++;
-
- while (func->next != NULL) {
- func = func->next;
-
- dbg("%s: In while loop, func-> bus %x device %x function %x pci_dev %p\n",
- __FUNCTION__, func->bus, func->device, func->function,
- func->pci_dev);
- if (func->device == device)
- found++;
- dbg("%s: while loop, found %d, index %d\n", __FUNCTION__,
- found, index);
-
- if ((found == index) || (func->function == index)) {
- dbg("%s: Found bus %x dev %x func %x\n", __FUNCTION__,
- func->bus, func->device, func->function);
- return func;
- }
- }
-
- return NULL;
-}
-
-static int is_bridge(struct pci_func * func)
-{
- /* Check the header type */
- if (((func->config_space[0x03] >> 16) & 0xFF) == 0x01)
- return 1;
- else
- return 0;
-}
-
-
/* The following routines constitute the bulk of the
hotplug controller logic
*/
@@ -1100,20 +269,17 @@ static void set_slot_off(struct controller *ctrl, struct slot * pslot)
* Configures board
*
*/
-static u32 board_added(struct pci_func * func, struct controller * ctrl)
+static int board_added(struct slot *p_slot)
{
u8 hp_slot;
- int index;
- u32 temp_register = 0xFFFFFFFF;
- u32 rc = 0;
- struct pci_func *new_func = NULL;
- struct slot *p_slot;
- struct resource_lists res_lists;
+ int rc = 0;
+ struct controller *ctrl = p_slot->ctrl;
- p_slot = pciehp_find_slot(ctrl, func->device);
- hp_slot = func->device - ctrl->slot_device_offset;
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
- dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
+ dbg("%s: slot device, slot offset, hp slot = %d, %d ,%d\n",
+ __FUNCTION__, p_slot->device,
+ ctrl->slot_device_offset, hp_slot);
/* Wait for exclusive access to hardware */
down(&ctrl->crit_sect);
@@ -1141,9 +307,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
up(&ctrl->crit_sect);
/* Wait for ~1 second */
- dbg("%s: before long_delay\n", __FUNCTION__);
wait_for_ctrl_irq (ctrl);
- dbg("%s: afterlong_delay\n", __FUNCTION__);
/* Check link training status */
rc = p_slot->hpc_ops->check_lnk_status(ctrl);
@@ -1153,98 +317,47 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
return rc;
}
- dbg("%s: func status = %x\n", __FUNCTION__, func->status);
+ dbg("%s: slot status = %x\n", __FUNCTION__, p_slot->status);
/* Check for a power fault */
- if (func->status == 0xFF) {
+ if (p_slot->status == 0xFF) {
/* power fault occurred, but it was benign */
- temp_register = 0xFFFFFFFF;
- dbg("%s: temp register set to %x by power fault\n", __FUNCTION__, temp_register);
rc = POWER_FAILURE;
- func->status = 0;
- } else {
- /* Get vendor/device ID u32 */
- rc = pci_bus_read_config_dword (ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function),
- PCI_VENDOR_ID, &temp_register);
- dbg("%s: pci_bus_read_config_dword returns %d\n", __FUNCTION__, rc);
- dbg("%s: temp_register is %x\n", __FUNCTION__, temp_register);
-
- if (rc != 0) {
- /* Something's wrong here */
- temp_register = 0xFFFFFFFF;
- dbg("%s: temp register set to %x by error\n", __FUNCTION__, temp_register);
- }
- /* Preset return code. It will be changed later if things go okay. */
- rc = NO_ADAPTER_PRESENT;
+ p_slot->status = 0;
+ goto err_exit;
}
- /* All F's is an empty slot or an invalid board */
- if (temp_register != 0xFFFFFFFF) { /* Check for a board in the slot */
- res_lists.io_head = ctrl->io_head;
- res_lists.mem_head = ctrl->mem_head;
- res_lists.p_mem_head = ctrl->p_mem_head;
- res_lists.bus_head = ctrl->bus_head;
- res_lists.irqs = NULL;
-
- rc = configure_new_device(ctrl, func, 0, &res_lists, 0, 0);
- dbg("%s: back from configure_new_device\n", __FUNCTION__);
-
- ctrl->io_head = res_lists.io_head;
- ctrl->mem_head = res_lists.mem_head;
- ctrl->p_mem_head = res_lists.p_mem_head;
- ctrl->bus_head = res_lists.bus_head;
+ rc = pciehp_configure_device(p_slot);
+ if (rc) {
+ err("Cannot add device 0x%x:%x\n", p_slot->bus,
+ p_slot->device);
+ goto err_exit;
+ }
- pciehp_resource_sort_and_combine(&(ctrl->mem_head));
- pciehp_resource_sort_and_combine(&(ctrl->p_mem_head));
- pciehp_resource_sort_and_combine(&(ctrl->io_head));
- pciehp_resource_sort_and_combine(&(ctrl->bus_head));
+ p_slot->status = 0;
- if (rc) {
- set_slot_off(ctrl, p_slot);
- return rc;
- }
- pciehp_save_slot_config(ctrl, func);
-
- func->status = 0;
- func->switch_save = 0x10;
- func->is_a_board = 0x01;
+ /*
+ * Some PCI Express root ports require fixup after hot-plug operation.
+ */
+ if (pcie_mch_quirk)
+ pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
+ if (PWR_LED(ctrl->ctrlcap)) {
+ /* Wait for exclusive access to hardware */
+ down(&ctrl->crit_sect);
- /* next, we will instantiate the linux pci_dev structures
- * (with appropriate driver notification, if already present)
- */
- index = 0;
- do {
- new_func = pciehp_slot_find(ctrl->slot_bus, func->device, index++);
- if (new_func && !new_func->pci_dev) {
- dbg("%s:call pci_hp_configure_dev, func %x\n",
- __FUNCTION__, index);
- pciehp_configure_device(ctrl, new_func);
- }
- } while (new_func);
-
- /*
- * Some PCI Express root ports require fixup after hot-plug operation.
- */
- if (pcie_mch_quirk)
- pci_fixup_device(pci_fixup_final, ctrl->pci_dev);
-
- if (PWR_LED(ctrl->ctrlcap)) {
- /* Wait for exclusive access to hardware */
- down(&ctrl->crit_sect);
-
- p_slot->hpc_ops->green_led_on(p_slot);
+ p_slot->hpc_ops->green_led_on(p_slot);
- /* Wait for the command to complete */
- wait_for_ctrl_irq (ctrl);
+ /* Wait for the command to complete */
+ wait_for_ctrl_irq (ctrl);
- /* Done with exclusive hardware access */
- up(&ctrl->crit_sect);
- }
- } else {
- set_slot_off(ctrl, p_slot);
- return -1;
- }
+ /* Done with exclusive hardware access */
+ up(&ctrl->crit_sect);
+ }
return 0;
+
+err_exit:
+ set_slot_off(ctrl, p_slot);
+ return -1;
}
@@ -1252,55 +365,25 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
* remove_board - Turns off slot and LED's
*
*/
-static u32 remove_board(struct pci_func *func, struct controller *ctrl)
+static int remove_board(struct slot *p_slot)
{
- int index;
- u8 skip = 0;
u8 device;
u8 hp_slot;
- u32 rc;
- struct resource_lists res_lists;
- struct pci_func *temp_func;
- struct slot *p_slot;
-
- if (func == NULL)
- return 1;
+ int rc;
+ struct controller *ctrl = p_slot->ctrl;
- if (pciehp_unconfigure_device(func))
+ if (pciehp_unconfigure_device(p_slot))
return 1;
- device = func->device;
+ device = p_slot->device;
- hp_slot = func->device - ctrl->slot_device_offset;
+ hp_slot = p_slot->device - ctrl->slot_device_offset;
p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
dbg("In %s, hp_slot = %d\n", __FUNCTION__, hp_slot);
- if ((ctrl->add_support) &&
- !(func->bus_head || func->mem_head || func->p_mem_head || func->io_head)) {
- /* Here we check to see if we've saved any of the board's
- * resources already. If so, we'll skip the attempt to
- * determine what's being used.
- */
- index = 0;
-
- temp_func = func;
-
- while ((temp_func = pciehp_slot_find(temp_func->bus, temp_func->device, index++))) {
- if (temp_func->bus_head || temp_func->mem_head
- || temp_func->p_mem_head || temp_func->io_head) {
- skip = 1;
- break;
- }
- }
-
- if (!skip)
- rc = pciehp_save_used_resources(ctrl, func, DISABLE_CARD);
- }
/* Change status to shutdown */
- if (func->is_a_board)
- func->status = 0x01;
- func->configured = 0;
+ p_slot->status = 0x01;
/* Wait for exclusive access to hardware */
down(&ctrl->crit_sect);
@@ -1328,56 +411,6 @@ static u32 remove_board(struct pci_func *func, struct controller *ctrl)
/* Done with exclusive hardware access */
up(&ctrl->crit_sect);
- if (ctrl->add_support) {
- while (func) {
- res_lists.io_head = ctrl->io_head;
- res_lists.mem_head = ctrl->mem_head;
- res_lists.p_mem_head = ctrl->p_mem_head;
- res_lists.bus_head = ctrl->bus_head;
-
- dbg("Returning resources to ctlr lists for (B/D/F) = (%#x/%#x/%#x)\n",
- func->bus, func->device, func->function);
-
- pciehp_return_board_resources(func, &res_lists);
-
- ctrl->io_head = res_lists.io_head;
- ctrl->mem_head = res_lists.mem_head;
- ctrl->p_mem_head = res_lists.p_mem_head;
- ctrl->bus_head = res_lists.bus_head;
-
- pciehp_resource_sort_and_combine(&(ctrl->mem_head));
- pciehp_resource_sort_and_combine(&(ctrl->p_mem_head));
- pciehp_resource_sort_and_combine(&(ctrl->io_head));
- pciehp_resource_sort_and_combine(&(ctrl->bus_head));
-
- if (is_bridge(func)) {
- dbg("PCI Bridge Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
- ctrl->seg, func->bus, func->device, func->function);
- bridge_slot_remove(func);
- } else {
- dbg("PCI Function Hot-Remove s:b:d:f(%02x:%02x:%02x:%02x)\n",
- ctrl->seg, func->bus, func->device, func->function);
- slot_remove(func);
- }
-
- func = pciehp_slot_find(ctrl->slot_bus, device, 0);
- }
-
- /* Setup slot structure with entry for empty slot */
- func = pciehp_slot_create(ctrl->slot_bus);
-
- if (func == NULL) {
- return 1;
- }
-
- func->bus = ctrl->slot_bus;
- func->device = device;
- func->function = 0;
- func->configured = 0;
- func->switch_save = 0x10;
- func->is_a_board = 0;
- }
-
return 0;
}
@@ -1411,13 +444,15 @@ static void pciehp_pushbutton_thread(unsigned long slot)
p_slot->hpc_ops->get_power_status(p_slot, &getstatus);
if (getstatus) {
p_slot->state = POWEROFF_STATE;
- dbg("In power_down_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+ dbg("%s: disabling bus:device(%x:%x)\n", __FUNCTION__,
+ p_slot->bus, p_slot->device);
pciehp_disable_slot(p_slot);
p_slot->state = STATIC_STATE;
} else {
p_slot->state = POWERON_STATE;
- dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+ dbg("%s: adding bus:device(%x:%x)\n", __FUNCTION__,
+ p_slot->bus, p_slot->device);
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */
@@ -1459,13 +494,15 @@ static void pciehp_surprise_rm_thread(unsigned long slot)
p_slot->hpc_ops->get_adapter_status(p_slot, &getstatus);
if (!getstatus) {
p_slot->state = POWEROFF_STATE;
- dbg("In removing board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+ dbg("%s: removing bus:device(%x:%x)\n",
+ __FUNCTION__, p_slot->bus, p_slot->device);
pciehp_disable_slot(p_slot);
p_slot->state = STATIC_STATE;
} else {
p_slot->state = POWERON_STATE;
- dbg("In add_board, b:d(%x:%x)\n", p_slot->bus, p_slot->device);
+ dbg("%s: adding bus:device(%x:%x)\n",
+ __FUNCTION__, p_slot->bus, p_slot->device);
if (pciehp_enable_slot(p_slot) && PWR_LED(p_slot->ctrl->ctrlcap)) {
/* Wait for exclusive access to hardware */
@@ -1531,7 +568,6 @@ int pciehp_event_start_thread(void)
err ("Can't start up our event thread\n");
return -1;
}
- dbg("Our event thread pid = %d\n", pid);
return 0;
}
@@ -1539,9 +575,7 @@ int pciehp_event_start_thread(void)
void pciehp_event_stop_thread(void)
{
event_finished = 1;
- dbg("event_thread finish command given\n");
up(&event_semaphore);
- dbg("wait for event_thread to exit\n");
down(&event_exit);
}
@@ -1573,7 +607,6 @@ static void interrupt_event_handler(struct controller *ctrl)
{
int loop = 0;
int change = 1;
- struct pci_func *func;
u8 hp_slot;
u8 getstatus;
struct slot *p_slot;
@@ -1581,16 +614,12 @@ static void interrupt_event_handler(struct controller *ctrl)
while (change) {
change = 0;
- for (loop = 0; loop < 10; loop++) {
+ for (loop = 0; loop < MAX_EVENTS; loop++) {
if (ctrl->event_queue[loop].event_type != 0) {
hp_slot = ctrl->event_queue[loop].hp_slot;
- func = pciehp_slot_find(ctrl->slot_bus, (hp_slot + ctrl->slot_device_offset), 0);
-
p_slot = pciehp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
- dbg("hp_slot %d, func %p, p_slot %p\n", hp_slot, func, p_slot);
-
if (ctrl->event_queue[loop].event_type == INT_BUTTON_CANCEL) {
dbg("button cancel\n");
del_timer(&p_slot->task_event);
@@ -1682,7 +711,6 @@ static void interrupt_event_handler(struct controller *ctrl)
p_slot->task_event.function = (void (*)(unsigned long)) pushbutton_helper_thread;
p_slot->task_event.data = (unsigned long) p_slot;
- dbg("add_timer p_slot = %p\n", (void *) p_slot);
add_timer(&p_slot->task_event);
}
}
@@ -1737,13 +765,6 @@ int pciehp_enable_slot(struct slot *p_slot)
{
u8 getstatus = 0;
int rc;
- struct pci_func *func;
-
- func = pciehp_slot_find(p_slot->bus, p_slot->device, 0);
- if (!func) {
- dbg("%s: Error! slot NULL\n", __FUNCTION__);
- return 1;
- }
/* Check to see if (latch closed, card present, power off) */
down(&p_slot->ctrl->crit_sect);
@@ -1773,45 +794,11 @@ int pciehp_enable_slot(struct slot *p_slot)
}
up(&p_slot->ctrl->crit_sect);
- slot_remove(func);
-
- func = pciehp_slot_create(p_slot->bus);
- if (func == NULL)
- return 1;
-
- func->bus = p_slot->bus;
- func->device = p_slot->device;
- func->function = 0;
- func->configured = 0;
- func->is_a_board = 1;
-
- /* We have to save the presence info for these slots */
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
- func->switch_save = !getstatus? 0x10:0;
- rc = board_added(func, p_slot->ctrl);
+ rc = board_added(p_slot);
if (rc) {
- if (is_bridge(func))
- bridge_slot_remove(func);
- else
- slot_remove(func);
-
- /* Setup slot structure with entry for empty slot */
- func = pciehp_slot_create(p_slot->bus);
- if (func == NULL)
- return 1; /* Out of memory */
-
- func->bus = p_slot->bus;
- func->device = p_slot->device;
- func->function = 0;
- func->configured = 0;
- func->is_a_board = 1;
-
- /* We have to save the presence info for these slots */
- p_slot->hpc_ops->get_adapter_status(p_slot, &(func->presence_save));
p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);
- func->switch_save = !getstatus? 0x10:0;
}
if (p_slot)
@@ -1823,14 +810,8 @@ int pciehp_enable_slot(struct slot *p_slot)
int pciehp_disable_slot(struct slot *p_slot)
{
- u8 class_code, header_type, BCR;
- u8 index = 0;
u8 getstatus = 0;
- u32 rc = 0;
int ret = 0;
- unsigned int devfn;
- struct pci_bus *pci_bus = p_slot->ctrl->pci_dev->subordinate;
- struct pci_func *func;
if (!p_slot->ctrl)
return 1;
@@ -1867,838 +848,8 @@ int pciehp_disable_slot(struct slot *p_slot)
up(&p_slot->ctrl->crit_sect);
- func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
-
- /* Make sure there are no video controllers here
- * for all func of p_slot
- */
- while (func && !rc) {
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* Check the Class Code */
- rc = pci_bus_read_config_byte (pci_bus, devfn, 0x0B, &class_code);
- if (rc)
- return rc;
-
- if (class_code == PCI_BASE_CLASS_DISPLAY) {
- /* Display/Video adapter (not supported) */
- rc = REMOVE_NOT_SUPPORTED;
- } else {
- /* See if it's a bridge */
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
- if (rc)
- return rc;
-
- /* If it's a bridge, check the VGA Enable bit */
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_byte (pci_bus, devfn, PCI_BRIDGE_CONTROL, &BCR);
- if (rc)
- return rc;
-
- /* If the VGA Enable bit is set, remove isn't supported */
- if (BCR & PCI_BRIDGE_CTL_VGA) {
- rc = REMOVE_NOT_SUPPORTED;
- }
- }
- }
-
- func = pciehp_slot_find(p_slot->bus, p_slot->device, index++);
- }
-
- func = pciehp_slot_find(p_slot->bus, p_slot->device, 0);
- if ((func != NULL) && !rc) {
- rc = remove_board(func, p_slot->ctrl);
- } else if (!rc)
- rc = 1;
-
- if (p_slot)
- update_slot_info(p_slot);
-
- return rc;
-}
-
-
-/**
- * configure_new_device - Configures the PCI header information of one board.
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Returns 0 if success
- *
- */
-static u32 configure_new_device(struct controller * ctrl, struct pci_func * func,
- u8 behind_bridge, struct resource_lists * resources, u8 bridge_bus, u8 bridge_dev)
-{
- u8 temp_byte, function, max_functions, stop_it;
- int rc;
- u32 ID;
- struct pci_func *new_slot;
- struct pci_bus lpci_bus, *pci_bus;
- int index;
-
- new_slot = func;
-
- dbg("%s\n", __FUNCTION__);
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
-
- /* Check for Multi-function device */
- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(func->device, func->function), 0x0E, &temp_byte);
- if (rc) {
- dbg("%s: rc = %d\n", __FUNCTION__, rc);
- return rc;
- }
-
- if (temp_byte & 0x80) /* Multi-function device */
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- rc = configure_new_function(ctrl, new_slot, behind_bridge,
- resources, bridge_bus, bridge_dev);
-
- if (rc) {
- dbg("configure_new_function failed: %d\n", rc);
- index = 0;
-
- while (new_slot) {
- new_slot = pciehp_slot_find(new_slot->bus,
- new_slot->device, index++);
-
- if (new_slot)
- pciehp_return_board_resources(new_slot,
- resources);
- }
-
- return rc;
- }
-
- function++;
-
- stop_it = 0;
-
- /* The following loop skips to the next present function
- * and creates a board structure
- */
-
- while ((function < max_functions) && (!stop_it)) {
- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(func->device, function), 0x00, &ID);
-
- if (ID == 0xFFFFFFFF) { /* There's nothing there. */
- function++;
- } else { /* There's something there */
- /* Setup slot structure. */
- new_slot = pciehp_slot_create(func->bus);
-
- if (new_slot == NULL) {
- /* Out of memory */
- return 1;
- }
-
- new_slot->bus = func->bus;
- new_slot->device = func->device;
- new_slot->function = function;
- new_slot->is_a_board = 1;
- new_slot->status = 0;
-
- stop_it++;
- }
- }
-
- } while (function < max_functions);
- dbg("returning from %s\n", __FUNCTION__);
-
- return 0;
-}
-
-/*
- * Configuration logic that involves the hotplug data structures and
- * their bookkeeping
- */
-
-/**
- * configure_bridge: fill bridge's registers, either configure or disable it.
- */
-static int
-configure_bridge(struct pci_bus *pci_bus, unsigned int devfn,
- struct pci_resource *mem_node,
- struct pci_resource **hold_mem_node,
- int base_addr, int limit_addr)
-{
- u16 temp_word;
- u32 rc;
-
- if (mem_node) {
- memcpy(*hold_mem_node, mem_node, sizeof(struct pci_resource));
- mem_node->next = NULL;
-
- /* set Mem base and Limit registers */
- RES_CHECK(mem_node->base, 16);
- temp_word = (u16)(mem_node->base >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word);
-
- RES_CHECK(mem_node->base + mem_node->length - 1, 16);
- temp_word = (u16)((mem_node->base + mem_node->length - 1) >> 16);
- rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word);
- } else {
- temp_word = 0xFFFF;
- rc = pci_bus_write_config_word(pci_bus, devfn, base_addr, temp_word);
-
- temp_word = 0x0000;
- rc = pci_bus_write_config_word(pci_bus, devfn, limit_addr, temp_word);
-
- kfree(*hold_mem_node);
- *hold_mem_node = NULL;
- }
- return rc;
-}
-
-static int
-configure_new_bridge(struct controller *ctrl, struct pci_func *func,
- u8 behind_bridge, struct resource_lists *resources,
- struct pci_bus *pci_bus)
-{
- int cloop;
- u8 temp_byte;
- u8 device;
- u16 temp_word;
- u32 rc;
- u32 ID;
- unsigned int devfn;
- struct pci_resource *mem_node;
- struct pci_resource *p_mem_node;
- struct pci_resource *io_node;
- struct pci_resource *bus_node;
- struct pci_resource *hold_mem_node;
- struct pci_resource *hold_p_mem_node;
- struct pci_resource *hold_IO_node;
- struct pci_resource *hold_bus_node;
- struct irq_mapping irqs;
- struct pci_func *new_slot;
- struct resource_lists temp_resources;
-
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* set Primary bus */
- dbg("set Primary bus = 0x%x\n", func->bus);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_PRIMARY_BUS, func->bus);
- if (rc)
- return rc;
-
- /* find range of busses to use */
- bus_node = get_max_resource(&resources->bus_head, 1L);
-
- /* If we don't have any busses to allocate, we can't continue */
- if (!bus_node) {
- err("Got NO bus resource to use\n");
- return -ENOMEM;
- }
- dbg("Got ranges of buses to use: base:len=0x%x:%x\n", bus_node->base, bus_node->length);
-
- /* set Secondary bus */
- temp_byte = (u8)bus_node->base;
- dbg("set Secondary bus = 0x%x\n", temp_byte);
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, temp_byte);
- if (rc)
- return rc;
-
- /* set subordinate bus */
- temp_byte = (u8)(bus_node->base + bus_node->length - 1);
- dbg("set subordinate bus = 0x%x\n", temp_byte);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
- if (rc)
- return rc;
-
- /* Set HP parameters (Cache Line Size, Latency Timer) */
- rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
- if (rc)
- return rc;
-
- /* Setup the IO, memory, and prefetchable windows */
-
- io_node = get_max_resource(&(resources->io_head), 0x1000L);
- if (io_node) {
- dbg("io_node(base, len, next) (%x, %x, %p)\n", io_node->base,
- io_node->length, io_node->next);
- }
-
- mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
- if (mem_node) {
- dbg("mem_node(base, len, next) (%x, %x, %p)\n", mem_node->base,
- mem_node->length, mem_node->next);
- }
-
- if (resources->p_mem_head)
- p_mem_node = get_max_resource(&(resources->p_mem_head), 0x100000L);
- else {
- /*
- * In some platform implementation, MEM and PMEM are not
- * distinguished, and hence ACPI _CRS has only MEM entries
- * for both MEM and PMEM.
- */
- dbg("using MEM for PMEM\n");
- p_mem_node = get_max_resource(&(resources->mem_head), 0x100000L);
- }
- if (p_mem_node) {
- dbg("p_mem_node(base, len, next) (%x, %x, %p)\n", p_mem_node->base,
- p_mem_node->length, p_mem_node->next);
- }
-
- /* set up the IRQ info */
- if (!resources->irqs) {
- irqs.barber_pole = 0;
- irqs.interrupt[0] = 0;
- irqs.interrupt[1] = 0;
- irqs.interrupt[2] = 0;
- irqs.interrupt[3] = 0;
- irqs.valid_INT = 0;
- } else {
- irqs.barber_pole = resources->irqs->barber_pole;
- irqs.interrupt[0] = resources->irqs->interrupt[0];
- irqs.interrupt[1] = resources->irqs->interrupt[1];
- irqs.interrupt[2] = resources->irqs->interrupt[2];
- irqs.interrupt[3] = resources->irqs->interrupt[3];
- irqs.valid_INT = resources->irqs->valid_INT;
- }
-
- /* set up resource lists that are now aligned on top and bottom
- * for anything behind the bridge.
- */
- temp_resources.bus_head = bus_node;
- temp_resources.io_head = io_node;
- temp_resources.mem_head = mem_node;
- temp_resources.p_mem_head = p_mem_node;
- temp_resources.irqs = &irqs;
-
- /* Make copies of the nodes we are going to pass down so that
- * if there is a problem,we can just use these to free resources
- */
- hold_bus_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- hold_IO_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- hold_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- hold_p_mem_node = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
-
- if (!hold_bus_node || !hold_IO_node || !hold_mem_node || !hold_p_mem_node) {
- kfree(hold_bus_node);
- kfree(hold_IO_node);
- kfree(hold_mem_node);
- kfree(hold_p_mem_node);
-
- return 1;
- }
-
- memcpy(hold_bus_node, bus_node, sizeof(struct pci_resource));
-
- bus_node->base += 1;
- bus_node->length -= 1;
- bus_node->next = NULL;
-
- /* If we have IO resources copy them and fill in the bridge's
- * IO range registers
- */
- if (io_node) {
- memcpy(hold_IO_node, io_node, sizeof(struct pci_resource));
- io_node->next = NULL;
-
- /* set IO base and Limit registers */
- RES_CHECK(io_node->base, 8);
- temp_byte = (u8)(io_node->base >> 8);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
- RES_CHECK(io_node->base + io_node->length - 1, 8);
- temp_byte = (u8)((io_node->base + io_node->length - 1) >> 8);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
- } else {
- kfree(hold_IO_node);
- hold_IO_node = NULL;
- }
-
- /* If we have memory resources copy them and fill in the bridge's
- * memory range registers. Otherwise, fill in the range
- * registers with values that disable them.
- */
- rc = configure_bridge(pci_bus, devfn, mem_node, &hold_mem_node,
- PCI_MEMORY_BASE, PCI_MEMORY_LIMIT);
-
- /* If we have prefetchable memory resources copy them and
- * fill in the bridge's memory range registers. Otherwise,
- * fill in the range registers with values that disable them.
- */
- rc = configure_bridge(pci_bus, devfn, p_mem_node, &hold_p_mem_node,
- PCI_PREF_MEMORY_BASE, PCI_PREF_MEMORY_LIMIT);
-
- /* Adjust this to compensate for extra adjustment in first loop */
- irqs.barber_pole--;
-
- rc = 0;
-
- /* Here we actually find the devices and configure them */
- for (device = 0; (device <= 0x1F) && !rc; device++) {
- irqs.barber_pole = (irqs.barber_pole + 1) & 0x03;
-
- ID = 0xFFFFFFFF;
- pci_bus->number = hold_bus_node->base;
- pci_bus_read_config_dword (pci_bus, PCI_DEVFN(device, 0), PCI_VENDOR_ID, &ID);
- pci_bus->number = func->bus;
-
- if (ID != 0xFFFFFFFF) { /* device Present */
- /* Setup slot structure. */
- new_slot = pciehp_slot_create(hold_bus_node->base);
-
- if (new_slot == NULL) {
- /* Out of memory */
- rc = -ENOMEM;
- continue;
- }
-
- new_slot->bus = hold_bus_node->base;
- new_slot->device = device;
- new_slot->function = 0;
- new_slot->is_a_board = 1;
- new_slot->status = 0;
-
- rc = configure_new_device(ctrl, new_slot, 1,
- &temp_resources, func->bus,
- func->device);
- dbg("configure_new_device rc=0x%x\n",rc);
- } /* End of IF (device in slot?) */
- } /* End of FOR loop */
-
- if (rc) {
- pciehp_destroy_resource_list(&temp_resources);
-
- return_resource(&(resources->bus_head), hold_bus_node);
- return_resource(&(resources->io_head), hold_IO_node);
- return_resource(&(resources->mem_head), hold_mem_node);
- return_resource(&(resources->p_mem_head), hold_p_mem_node);
- return(rc);
- }
-
- /* save the interrupt routing information */
- if (resources->irqs) {
- resources->irqs->interrupt[0] = irqs.interrupt[0];
- resources->irqs->interrupt[1] = irqs.interrupt[1];
- resources->irqs->interrupt[2] = irqs.interrupt[2];
- resources->irqs->interrupt[3] = irqs.interrupt[3];
- resources->irqs->valid_INT = irqs.valid_INT;
- } else if (!behind_bridge) {
- /* We need to hook up the interrupts here */
- for (cloop = 0; cloop < 4; cloop++) {
- if (irqs.valid_INT & (0x01 << cloop)) {
- rc = pciehp_set_irq(func->bus, func->device,
- 0x0A + cloop, irqs.interrupt[cloop]);
- if (rc) {
- pciehp_destroy_resource_list (&temp_resources);
- return_resource(&(resources->bus_head), hold_bus_node);
- return_resource(&(resources->io_head), hold_IO_node);
- return_resource(&(resources->mem_head), hold_mem_node);
- return_resource(&(resources->p_mem_head), hold_p_mem_node);
- return rc;
- }
- }
- } /* end of for loop */
- }
-
- /* Return unused bus resources
- * First use the temporary node to store information for the board
- */
- if (hold_bus_node && bus_node && temp_resources.bus_head) {
- hold_bus_node->length = bus_node->base - hold_bus_node->base;
-
- hold_bus_node->next = func->bus_head;
- func->bus_head = hold_bus_node;
-
- temp_byte = (u8)(temp_resources.bus_head->base - 1);
-
- /* set subordinate bus */
- dbg("re-set subordinate bus = 0x%x\n", temp_byte);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_SUBORDINATE_BUS, temp_byte);
-
- if (temp_resources.bus_head->length == 0) {
- kfree(temp_resources.bus_head);
- temp_resources.bus_head = NULL;
- } else {
- dbg("return bus res of b:d(0x%x:%x) base:len(0x%x:%x)\n",
- func->bus, func->device, temp_resources.bus_head->base, temp_resources.bus_head->length);
- return_resource(&(resources->bus_head), temp_resources.bus_head);
- }
- }
-
- /* If we have IO space available and there is some left,
- * return the unused portion
- */
- if (hold_IO_node && temp_resources.io_head) {
- io_node = do_pre_bridge_resource_split(&(temp_resources.io_head),
- &hold_IO_node, 0x1000);
-
- /* Check if we were able to split something off */
- if (io_node) {
- hold_IO_node->base = io_node->base + io_node->length;
-
- RES_CHECK(hold_IO_node->base, 8);
- temp_byte = (u8)((hold_IO_node->base) >> 8);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_BASE, temp_byte);
-
- return_resource(&(resources->io_head), io_node);
- }
-
- io_node = do_bridge_resource_split(&(temp_resources.io_head), 0x1000);
-
- /* Check if we were able to split something off */
- if (io_node) {
- /* First use the temporary node to store information for the board */
- hold_IO_node->length = io_node->base - hold_IO_node->base;
-
- /* If we used any, add it to the board's list */
- if (hold_IO_node->length) {
- hold_IO_node->next = func->io_head;
- func->io_head = hold_IO_node;
-
- RES_CHECK(io_node->base - 1, 8);
- temp_byte = (u8)((io_node->base - 1) >> 8);
- rc = pci_bus_write_config_byte (pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
- return_resource(&(resources->io_head), io_node);
- } else {
- /* it doesn't need any IO */
- temp_byte = 0x00;
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_IO_LIMIT, temp_byte);
-
- return_resource(&(resources->io_head), io_node);
- kfree(hold_IO_node);
- }
- } else {
- /* it used most of the range */
- hold_IO_node->next = func->io_head;
- func->io_head = hold_IO_node;
- }
- } else if (hold_IO_node) {
- /* it used the whole range */
- hold_IO_node->next = func->io_head;
- func->io_head = hold_IO_node;
- }
-
- /* If we have memory space available and there is some left,
- * return the unused portion
- */
- if (hold_mem_node && temp_resources.mem_head) {
- mem_node = do_pre_bridge_resource_split(&(temp_resources.mem_head), &hold_mem_node, 0x100000L);
-
- /* Check if we were able to split something off */
- if (mem_node) {
- hold_mem_node->base = mem_node->base + mem_node->length;
-
- RES_CHECK(hold_mem_node->base, 16);
- temp_word = (u16)((hold_mem_node->base) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_BASE, temp_word);
-
- return_resource(&(resources->mem_head), mem_node);
- }
-
- mem_node = do_bridge_resource_split(&(temp_resources.mem_head), 0x100000L);
-
- /* Check if we were able to split something off */
- if (mem_node) {
- /* First use the temporary node to store information for the board */
- hold_mem_node->length = mem_node->base - hold_mem_node->base;
-
- if (hold_mem_node->length) {
- hold_mem_node->next = func->mem_head;
- func->mem_head = hold_mem_node;
-
- /* configure end address */
- RES_CHECK(mem_node->base - 1, 16);
- temp_word = (u16)((mem_node->base - 1) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
- /* Return unused resources to the pool */
- return_resource(&(resources->mem_head), mem_node);
- } else {
- /* it doesn't need any Mem */
- temp_word = 0x0000;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_MEMORY_LIMIT, temp_word);
-
- return_resource(&(resources->mem_head), mem_node);
- kfree(hold_mem_node);
- }
- } else {
- /* it used most of the range */
- hold_mem_node->next = func->mem_head;
- func->mem_head = hold_mem_node;
- }
- } else if (hold_mem_node) {
- /* it used the whole range */
- hold_mem_node->next = func->mem_head;
- func->mem_head = hold_mem_node;
- }
-
- /* If we have prefetchable memory space available and there is some
- * left at the end, return the unused portion
- */
- if (hold_p_mem_node && temp_resources.p_mem_head) {
- p_mem_node = do_pre_bridge_resource_split(&(temp_resources.p_mem_head),
- &hold_p_mem_node, 0x100000L);
-
- /* Check if we were able to split something off */
- if (p_mem_node) {
- hold_p_mem_node->base = p_mem_node->base + p_mem_node->length;
-
- RES_CHECK(hold_p_mem_node->base, 16);
- temp_word = (u16)((hold_p_mem_node->base) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_BASE, temp_word);
-
- return_resource(&(resources->p_mem_head), p_mem_node);
- }
-
- p_mem_node = do_bridge_resource_split(&(temp_resources.p_mem_head), 0x100000L);
-
- /* Check if we were able to split something off */
- if (p_mem_node) {
- /* First use the temporary node to store information for the board */
- hold_p_mem_node->length = p_mem_node->base - hold_p_mem_node->base;
-
- /* If we used any, add it to the board's list */
- if (hold_p_mem_node->length) {
- hold_p_mem_node->next = func->p_mem_head;
- func->p_mem_head = hold_p_mem_node;
-
- RES_CHECK(p_mem_node->base - 1, 16);
- temp_word = (u16)((p_mem_node->base - 1) >> 16);
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
- return_resource(&(resources->p_mem_head), p_mem_node);
- } else {
- /* it doesn't need any PMem */
- temp_word = 0x0000;
- rc = pci_bus_write_config_word (pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, temp_word);
-
- return_resource(&(resources->p_mem_head), p_mem_node);
- kfree(hold_p_mem_node);
- }
- } else {
- /* it used the most of the range */
- hold_p_mem_node->next = func->p_mem_head;
- func->p_mem_head = hold_p_mem_node;
- }
- } else if (hold_p_mem_node) {
- /* it used the whole range */
- hold_p_mem_node->next = func->p_mem_head;
- func->p_mem_head = hold_p_mem_node;
- }
-
- /* We should be configuring an IRQ and the bridge's base address
- * registers if it needs them. Although we have never seen such
- * a device
- */
-
- pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_BRIDGE);
-
- dbg("PCI Bridge Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device, func->function);
-
- return rc;
+ ret = remove_board(p_slot);
+ update_slot_info(p_slot);
+ return ret;
}
-/**
- * configure_new_function - Configures the PCI header information of one device
- *
- * @ctrl: pointer to controller structure
- * @func: pointer to function structure
- * @behind_bridge: 1 if this is a recursive call, 0 if not
- * @resources: pointer to set of resource lists
- *
- * Calls itself recursively for bridged devices.
- * Returns 0 if success
- *
- */
-static int
-configure_new_function(struct controller *ctrl, struct pci_func *func,
- u8 behind_bridge, struct resource_lists *resources,
- u8 bridge_bus, u8 bridge_dev)
-{
- int cloop;
- u8 temp_byte;
- u8 class_code;
- u32 rc;
- u32 temp_register;
- u32 base;
- unsigned int devfn;
- struct pci_resource *mem_node;
- struct pci_resource *io_node;
- struct pci_bus lpci_bus, *pci_bus;
-
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* Check for Bridge */
- rc = pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &temp_byte);
- if (rc)
- return rc;
- dbg("%s: bus %x dev %x func %x temp_byte = %x\n", __FUNCTION__,
- func->bus, func->device, func->function, temp_byte);
-
- if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
- rc = configure_new_bridge(ctrl, func, behind_bridge, resources,
- pci_bus);
-
- if (rc)
- return rc;
- } else if ((temp_byte & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
- /* Standard device */
- u64 base64;
- rc = pci_bus_read_config_byte(pci_bus, devfn, 0x0B, &class_code);
-
- if (class_code == PCI_BASE_CLASS_DISPLAY)
- return DEVICE_TYPE_NOT_SUPPORTED;
-
- /* Figure out IO and memory needs */
- for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
- temp_register = 0xFFFFFFFF;
-
- rc = pci_bus_write_config_dword (pci_bus, devfn, cloop, temp_register);
- rc = pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
- dbg("Bar[%x]=0x%x on bus:dev:func(0x%x:%x:%x)\n", cloop, temp_register,
- func->bus, func->device, func->function);
-
- if (!temp_register)
- continue;
-
- base64 = 0L;
- if (temp_register & PCI_BASE_ADDRESS_SPACE_IO) {
- /* Map IO */
-
- /* set base = amount of IO space */
- base = temp_register & 0xFFFFFFFC;
- base = ~base + 1;
-
- dbg("NEED IO length(0x%x)\n", base);
- io_node = get_io_resource(&(resources->io_head),(ulong)base);
-
- /* allocate the resource to the board */
- if (io_node) {
- dbg("Got IO base=0x%x(length=0x%x)\n", io_node->base, io_node->length);
- base = (u32)io_node->base;
- io_node->next = func->io_head;
- func->io_head = io_node;
- } else {
- err("Got NO IO resource(length=0x%x)\n", base);
- return -ENOMEM;
- }
- } else { /* map MEM */
- int prefetchable = 1;
- struct pci_resource **res_node = &func->p_mem_head;
- char *res_type_str = "PMEM";
- u32 temp_register2;
-
- if (!(temp_register & PCI_BASE_ADDRESS_MEM_PREFETCH)) {
- prefetchable = 0;
- res_node = &func->mem_head;
- res_type_str++;
- }
-
- base = temp_register & 0xFFFFFFF0;
- base = ~base + 1;
-
- switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- dbg("NEED 32 %s bar=0x%x(length=0x%x)\n", res_type_str, temp_register, base);
-
- if (prefetchable && resources->p_mem_head)
- mem_node=get_resource(&(resources->p_mem_head), (ulong)base);
- else {
- if (prefetchable)
- dbg("using MEM for PMEM\n");
- mem_node = get_resource(&(resources->mem_head), (ulong)base);
- }
-
- /* allocate the resource to the board */
- if (mem_node) {
- base = (u32)mem_node->base;
- mem_node->next = *res_node;
- *res_node = mem_node;
- dbg("Got 32 %s base=0x%x(length=0x%x)\n", res_type_str, mem_node->base,
- mem_node->length);
- } else {
- err("Got NO 32 %s resource(length=0x%x)\n", res_type_str, base);
- return -ENOMEM;
- }
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- rc = pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
- dbg("NEED 64 %s bar=0x%x:%x(length=0x%x)\n", res_type_str, temp_register2,
- temp_register, base);
-
- if (prefetchable && resources->p_mem_head)
- mem_node = get_resource(&(resources->p_mem_head), (ulong)base);
- else {
- if (prefetchable)
- dbg("using MEM for PMEM\n");
- mem_node = get_resource(&(resources->mem_head), (ulong)base);
- }
-
- /* allocate the resource to the board */
- if (mem_node) {
- base64 = mem_node->base;
- mem_node->next = *res_node;
- *res_node = mem_node;
- dbg("Got 64 %s base=0x%x:%x(length=%x)\n", res_type_str, (u32)(base64 >> 32),
- (u32)base64, mem_node->length);
- } else {
- err("Got NO 64 %s resource(length=0x%x)\n", res_type_str, base);
- return -ENOMEM;
- }
- break;
- default:
- dbg("reserved BAR type=0x%x\n", temp_register);
- break;
- }
-
- }
-
- if (base64) {
- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
- cloop += 4;
- base64 >>= 32;
-
- if (base64) {
- dbg("%s: high dword of base64(0x%x) set to 0\n", __FUNCTION__, (u32)base64);
- base64 = 0x0L;
- }
-
- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, (u32)base64);
- } else {
- rc = pci_bus_write_config_dword(pci_bus, devfn, cloop, base);
- }
- } /* End of base register loop */
-
- /* disable ROM base Address */
- rc = pci_bus_write_config_dword (pci_bus, devfn, PCI_ROM_ADDRESS, 0x00);
-
- /* Set HP parameters (Cache Line Size, Latency Timer) */
- rc = pciehprm_set_hpp(ctrl, func, PCI_HEADER_TYPE_NORMAL);
- if (rc)
- return rc;
-
- pciehprm_enable_card(ctrl, func, PCI_HEADER_TYPE_NORMAL);
-
- dbg("PCI function Hot-Added s:b:d:f(%02x:%02x:%02x:%02x)\n", ctrl->seg, func->bus, func->device,
- func->function);
- } /* End of Not-A-Bridge else */
- else {
- /* It's some strange type of PCI adapter (Cardbus?) */
- return DEVICE_TYPE_NOT_SUPPORTED;
- }
-
- func->configured = 1;
-
- return 0;
-}
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 7a0e27f0e063..4a3cecca012c 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -27,16 +27,10 @@
*
*/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-#include <linux/interrupt.h>
-#include <linux/spinlock.h>
#include <linux/pci.h>
-#include <asm/system.h>
#include "../pci.h"
#include "pciehp.h"
@@ -217,23 +211,6 @@ static int pcie_cap_base = 0; /* Base of the PCI Express capability item struct
#define MRL_STATE 0x0020
#define PRSN_STATE 0x0040
-struct php_ctlr_state_s {
- struct php_ctlr_state_s *pnext;
- struct pci_dev *pci_dev;
- unsigned int irq;
- unsigned long flags; /* spinlock's */
- u32 slot_device_offset;
- u32 num_slots;
- struct timer_list int_poll_timer; /* Added for poll event */
- php_intr_callback_t attention_button_callback;
- php_intr_callback_t switch_change_callback;
- php_intr_callback_t presence_change_callback;
- php_intr_callback_t power_fault_callback;
- void *callback_instance_id;
- struct ctrl_reg *creg; /* Ptr to controller register space */
-};
-
-
static spinlock_t hpc_event_lock;
DEFINE_DBG_BUFFER /* Debug string buffer for entire HPC defined here */
@@ -297,7 +274,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
DBG_ENTER_ROUTINE
- dbg("%s : Enter\n", __FUNCTION__);
if (!php_ctlr) {
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
return -1;
@@ -308,7 +284,6 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return retval;
}
- dbg("%s : hp_register_read_word SLOT_STATUS %x\n", __FUNCTION__, slot_status);
if ((slot_status & CMD_COMPLETED) == CMD_COMPLETED ) {
/* After 1 sec and CMD_COMPLETED still not set, just proceed forward to issue
@@ -316,14 +291,11 @@ static int pcie_write_cmd(struct slot *slot, u16 cmd)
dbg("%s : CMD_COMPLETED not clear after 1 sec.\n", __FUNCTION__);
}
- dbg("%s: Before hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd);
retval = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(slot->ctrl->cap_base), cmd | CMD_CMPL_INTR_ENABLE);
if (retval) {
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s : hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, cmd | CMD_CMPL_INTR_ENABLE);
- dbg("%s : Exit\n", __FUNCTION__);
DBG_LEAVE_ROUTINE
return retval;
@@ -509,7 +481,6 @@ static int hpc_query_power_fault(struct slot * slot)
u16 slot_status;
u8 pwr_fault;
int retval = 0;
- u8 status;
DBG_ENTER_ROUTINE
@@ -521,15 +492,13 @@ static int hpc_query_power_fault(struct slot * slot)
retval = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(slot->ctrl->cap_base), slot_status);
if (retval) {
- err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
+ err("%s : Cannot check for power fault\n", __FUNCTION__);
return retval;
}
pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1);
- status = (pwr_fault != 1) ? 1 : 0;
DBG_LEAVE_ROUTINE
- /* Note: Logic 0 => fault */
- return status;
+ return pwr_fault;
}
static int hpc_set_attention_status(struct slot *slot, u8 value)
@@ -539,7 +508,8 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
u16 slot_ctrl;
int rc = 0;
- dbg("%s: \n", __FUNCTION__);
+ DBG_ENTER_ROUTINE
+
if (!php_ctlr) {
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
return -1;
@@ -555,7 +525,6 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return rc;
}
- dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
switch (value) {
case 0 : /* turn off */
@@ -576,6 +545,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
pcie_write_cmd(slot, slot_cmd);
dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
+ DBG_LEAVE_ROUTINE
return rc;
}
@@ -587,7 +557,8 @@ static void hpc_set_green_led_on(struct slot *slot)
u16 slot_ctrl;
int rc = 0;
- dbg("%s: \n", __FUNCTION__);
+ DBG_ENTER_ROUTINE
+
if (!php_ctlr) {
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
return ;
@@ -604,7 +575,6 @@ static void hpc_set_green_led_on(struct slot *slot)
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return;
}
- dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0100;
if (!pciehp_poll_mode)
slot_cmd = slot_cmd | HP_INTR_ENABLE;
@@ -612,6 +582,7 @@ static void hpc_set_green_led_on(struct slot *slot)
pcie_write_cmd(slot, slot_cmd);
dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
+ DBG_LEAVE_ROUTINE
return;
}
@@ -622,7 +593,8 @@ static void hpc_set_green_led_off(struct slot *slot)
u16 slot_ctrl;
int rc = 0;
- dbg("%s: \n", __FUNCTION__);
+ DBG_ENTER_ROUTINE
+
if (!php_ctlr) {
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
return ;
@@ -639,7 +611,6 @@ static void hpc_set_green_led_off(struct slot *slot)
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return;
}
- dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0300;
@@ -648,6 +619,7 @@ static void hpc_set_green_led_off(struct slot *slot)
pcie_write_cmd(slot, slot_cmd);
dbg("%s: SLOT_CTRL %x write cmd %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
+ DBG_LEAVE_ROUTINE
return;
}
@@ -658,7 +630,8 @@ static void hpc_set_green_led_blink(struct slot *slot)
u16 slot_ctrl;
int rc = 0;
- dbg("%s: \n", __FUNCTION__);
+ DBG_ENTER_ROUTINE
+
if (!php_ctlr) {
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
return ;
@@ -675,7 +648,6 @@ static void hpc_set_green_led_blink(struct slot *slot)
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return;
}
- dbg("%s : hp_register_read_word SLOT_CTRL %x\n", __FUNCTION__, slot_ctrl);
slot_cmd = (slot_ctrl & ~PWR_LED_CTRL) | 0x0200;
@@ -684,6 +656,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
pcie_write_cmd(slot, slot_cmd);
dbg("%s: SLOT_CTRL %x write cmd %x\n",__FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base), slot_cmd);
+ DBG_LEAVE_ROUTINE
return;
}
@@ -780,7 +753,6 @@ static int hpc_power_on_slot(struct slot * slot)
int retval = 0;
DBG_ENTER_ROUTINE
- dbg("%s: \n", __FUNCTION__);
if (!php_ctlr) {
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
@@ -799,8 +771,6 @@ static int hpc_power_on_slot(struct slot * slot)
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x, value read %xn", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
- slot_ctrl);
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_ON;
@@ -829,7 +799,6 @@ static int hpc_power_off_slot(struct slot * slot)
int retval = 0;
DBG_ENTER_ROUTINE
- dbg("%s: \n", __FUNCTION__);
if (!php_ctlr) {
err("%s: Invalid HPC controller handle!\n", __FUNCTION__);
@@ -848,8 +817,6 @@ static int hpc_power_off_slot(struct slot * slot)
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
return retval;
}
- dbg("%s: SLOT_CTRL %x, value read %x\n", __FUNCTION__, SLOT_CTRL(slot->ctrl->cap_base),
- slot_ctrl);
slot_cmd = (slot_ctrl & ~PWR_CTRL) | POWER_OFF;
@@ -924,7 +891,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
return IRQ_NONE;
}
- dbg("%s: Set Mask Hot-plug Interrupt Enable\n", __FUNCTION__);
dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00;
@@ -933,7 +899,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
}
- dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
@@ -949,14 +914,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
}
- dbg("%s: hp_register_write_word SLOT_STATUS with value %x\n", __FUNCTION__, temp_word);
}
if (intr_loc & CMD_COMPLETED) {
/*
* Command Complete Interrupt Pending
*/
- dbg("%s: In Command Complete Interrupt Pending\n", __FUNCTION__);
wake_up_interruptible(&ctrl->queue);
}
@@ -989,7 +952,6 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
}
dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__);
- dbg("%s: hp_register_read_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_CTRL(ctrl->cap_base), temp_word);
@@ -997,14 +959,12 @@ static irqreturn_t pcie_isr(int IRQ, void *dev_id, struct pt_regs *regs)
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
return IRQ_NONE;
}
- dbg("%s: hp_register_write_word SLOT_CTRL with value %x\n", __FUNCTION__, temp_word);
rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
return IRQ_NONE;
}
- dbg("%s: hp_register_read_word SLOT_STATUS with value %x\n", __FUNCTION__, slot_status);
/* Clear command complete interrupt caused by this write */
temp_word = 0x1F;
@@ -1248,12 +1208,7 @@ static struct hpc_ops pciehp_hpc_ops = {
.check_lnk_status = hpc_check_lnk_status,
};
-int pcie_init(struct controller * ctrl,
- struct pcie_device *dev,
- php_intr_callback_t attention_button_callback,
- php_intr_callback_t switch_change_callback,
- php_intr_callback_t presence_change_callback,
- php_intr_callback_t power_fault_callback)
+int pcie_init(struct controller * ctrl, struct pcie_device *dev)
{
struct php_ctlr_state_s *php_ctlr, *p;
void *instance_id = ctrl;
@@ -1282,8 +1237,8 @@ int pcie_init(struct controller * ctrl,
pdev = dev->port;
php_ctlr->pci_dev = pdev; /* save pci_dev in context */
- dbg("%s: pdev->vendor %x pdev->device %x\n", __FUNCTION__,
- pdev->vendor, pdev->device);
+ dbg("%s: hotplug controller vendor id 0x%x device id 0x%x\n",
+ __FUNCTION__, pdev->vendor, pdev->device);
saved_cap_base = pcie_cap_base;
@@ -1340,8 +1295,6 @@ int pcie_init(struct controller * ctrl,
first = 0;
}
- dbg("pdev = %p: b:d:f:irq=0x%x:%x:%x:%x\n", pdev, pdev->bus->number,
- PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), dev->irq);
for ( rc = 0; rc < DEVICE_COUNT_RESOURCE; rc++)
if (pci_resource_len(pdev, rc) > 0)
dbg("pci resource[%d] start=0x%lx(len=0x%lx)\n", rc,
@@ -1359,13 +1312,12 @@ int pcie_init(struct controller * ctrl,
/* find the IRQ */
php_ctlr->irq = dev->irq;
- dbg("HPC interrupt = %d\n", php_ctlr->irq);
/* Save interrupt callback info */
- php_ctlr->attention_button_callback = attention_button_callback;
- php_ctlr->switch_change_callback = switch_change_callback;
- php_ctlr->presence_change_callback = presence_change_callback;
- php_ctlr->power_fault_callback = power_fault_callback;
+ php_ctlr->attention_button_callback = pciehp_handle_attention_button;
+ php_ctlr->switch_change_callback = pciehp_handle_switch_change;
+ php_ctlr->presence_change_callback = pciehp_handle_presence_change;
+ php_ctlr->power_fault_callback = pciehp_handle_power_fault;
php_ctlr->callback_instance_id = instance_id;
/* return PCI Controller Info */
@@ -1387,15 +1339,12 @@ int pcie_init(struct controller * ctrl,
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s : Mask HPIE hp_register_write_word SLOT_CTRL %x\n", __FUNCTION__, temp_word);
rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: Mask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base)
- , slot_status);
temp_word = 0x1F; /* Clear all events */
rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
@@ -1403,7 +1352,6 @@ int pcie_init(struct controller * ctrl,
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
if (pciehp_poll_mode) {/* Install interrupt polling code */
/* Install and start the interrupt polling timer */
@@ -1419,13 +1367,14 @@ int pcie_init(struct controller * ctrl,
}
}
+ 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);
+
rc = hp_register_read_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
if (rc) {
err("%s : hp_register_read_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_CTRL %x value read %x\n", __FUNCTION__, SLOT_CTRL(ctrl->cap_base), temp_word);
- dbg("%s: slot_cap %x\n", __FUNCTION__, slot_cap);
intr_enable = intr_enable | PRSN_DETECT_ENABLE;
@@ -1445,7 +1394,6 @@ int pcie_init(struct controller * ctrl,
} else {
temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
}
- dbg("%s: temp_word %x\n", __FUNCTION__, temp_word);
/* Unmask Hot-plug Interrupt Enable for the interrupt notification mechanism case */
rc = hp_register_write_word(pdev, SLOT_CTRL(ctrl->cap_base), temp_word);
@@ -1453,14 +1401,11 @@ int pcie_init(struct controller * ctrl,
err("%s : hp_register_write_word SLOT_CTRL failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s : Unmask HPIE hp_register_write_word SLOT_CTRL with %x\n", __FUNCTION__, temp_word);
rc = hp_register_read_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), slot_status);
if (rc) {
err("%s : hp_register_read_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: Unmask HPIE SLOT_STATUS offset %x reads slot_status %x\n", __FUNCTION__,
- SLOT_STATUS(ctrl->cap_base), slot_status);
temp_word = 0x1F; /* Clear all events */
rc = hp_register_write_word(php_ctlr->pci_dev, SLOT_STATUS(ctrl->cap_base), temp_word);
@@ -1468,8 +1413,16 @@ int pcie_init(struct controller * ctrl,
err("%s : hp_register_write_word SLOT_STATUS failed\n", __FUNCTION__);
goto abort_free_ctlr;
}
- dbg("%s: SLOT_STATUS offset %x writes slot_status %x\n", __FUNCTION__, SLOT_STATUS(ctrl->cap_base), temp_word);
+ if (pciehp_force) {
+ dbg("Bypassing BIOS check for pciehp use on %s\n",
+ pci_name(ctrl->pci_dev));
+ } else {
+ rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev);
+ if (rc)
+ goto abort_free_ctlr;
+ }
+
/* Add this HPC instance into the HPC list */
spin_lock(&list_lock);
if (php_ctlr_list_head == 0) {
diff --git a/drivers/pci/hotplug/pciehp_pci.c b/drivers/pci/hotplug/pciehp_pci.c
index ff17d8e07e94..647673a7d224 100644
--- a/drivers/pci/hotplug/pciehp_pci.c
+++ b/drivers/pci/hotplug/pciehp_pci.c
@@ -27,801 +27,111 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include <linux/proc_fs.h>
#include <linux/pci.h>
#include "../pci.h"
#include "pciehp.h"
-#ifndef CONFIG_IA64
-#include "../../../arch/i386/pci/pci.h" /* horrible hack showing how processor dependant we are... */
-#endif
-int pciehp_configure_device (struct controller* ctrl, struct pci_func* func)
+int pciehp_configure_device(struct slot *p_slot)
{
- unsigned char bus;
- struct pci_bus *child;
- int num;
-
- if (func->pci_dev == NULL)
- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
-
- /* Still NULL ? Well then scan for it ! */
- if (func->pci_dev == NULL) {
- dbg("%s: pci_dev still null. do pci_scan_slot\n", __FUNCTION__);
-
- num = pci_scan_slot(ctrl->pci_dev->subordinate, PCI_DEVFN(func->device, func->function));
-
- if (num)
- pci_bus_add_devices(ctrl->pci_dev->subordinate);
-
- func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
- if (func->pci_dev == NULL) {
- dbg("ERROR: pci_dev still null\n");
- return 0;
- }
+ struct pci_dev *dev;
+ struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
+ int num, fn;
+
+ dev = pci_find_slot(p_slot->bus, PCI_DEVFN(p_slot->device, 0));
+ if (dev) {
+ err("Device %s already exists at %x:%x, cannot hot-add\n",
+ pci_name(dev), p_slot->bus, p_slot->device);
+ return -EINVAL;
}
- if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
- pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
- child = pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
- pci_do_scan_bus(child);
+ num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
+ if (num == 0) {
+ err("No new device found\n");
+ return -ENODEV;
+ }
+ for (fn = 0; fn < 8; fn++) {
+ if (!(dev = pci_find_slot(p_slot->bus,
+ PCI_DEVFN(p_slot->device, fn))))
+ continue;
+ if ((dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+ err("Cannot hot-add display device %s\n",
+ pci_name(dev));
+ continue;
+ }
+ if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
+ (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
+ /* Find an unused bus number for the new bridge */
+ struct pci_bus *child;
+ unsigned char busnr, start = parent->secondary;
+ unsigned char end = parent->subordinate;
+ for (busnr = start; busnr <= end; busnr++) {
+ if (!pci_find_bus(pci_domain_nr(parent),
+ busnr))
+ break;
+ }
+ if (busnr >= end) {
+ err("No free bus for hot-added bridge\n");
+ continue;
+ }
+ child = pci_add_new_bus(parent, dev, busnr);
+ if (!child) {
+ err("Cannot add new bus for %s\n",
+ pci_name(dev));
+ continue;
+ }
+ child->subordinate = pci_do_scan_bus(child);
+ pci_bus_size_bridges(child);
+ }
+ /* TBD: program firmware provided _HPP values */
+ /* program_fw_provided_values(dev); */
}
+ pci_bus_assign_resources(parent);
+ pci_bus_add_devices(parent);
+ pci_enable_bridges(parent);
return 0;
}
-
-int pciehp_unconfigure_device(struct pci_func* func)
+int pciehp_unconfigure_device(struct slot *p_slot)
{
int rc = 0;
int j;
- struct pci_bus *pbus;
+ u8 bctl = 0;
- dbg("%s: bus/dev/func = %x/%x/%x\n", __FUNCTION__, func->bus,
- func->device, func->function);
- pbus = func->pci_dev->bus;
+ dbg("%s: bus/dev = %x/%x\n", __FUNCTION__, p_slot->bus,
+ p_slot->device);
for (j=0; j<8 ; j++) {
- struct pci_dev* temp = pci_find_slot(func->bus,
- (func->device << 3) | j);
- if (temp) {
- pci_remove_bus_device(temp);
+ struct pci_dev* temp = pci_find_slot(p_slot->bus,
+ (p_slot->device << 3) | j);
+ if (!temp)
+ continue;
+ if ((temp->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
+ err("Cannot remove display device %s\n",
+ pci_name(temp));
+ continue;
}
+ if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
+ if (bctl & PCI_BRIDGE_CTL_VGA) {
+ err("Cannot remove display device %s\n",
+ pci_name(temp));
+ continue;
+ }
+ }
+ pci_remove_bus_device(temp);
}
/*
* Some PCI Express root ports require fixup after hot-plug operation.
*/
if (pcie_mch_quirk)
- pci_fixup_device(pci_fixup_final, pbus->self);
+ pci_fixup_device(pci_fixup_final, p_slot->ctrl->pci_dev);
return rc;
}
-/*
- * pciehp_set_irq
- *
- * @bus_num: bus number of PCI device
- * @dev_num: device number of PCI device
- * @slot: pointer to u8 where slot number will be returned
- */
-int pciehp_set_irq (u8 bus_num, u8 dev_num, u8 int_pin, u8 irq_num)
-{
-#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_IO_APIC)
- int rc;
- u16 temp_word;
- struct pci_dev fakedev;
- struct pci_bus fakebus;
-
- fakedev.devfn = dev_num << 3;
- fakedev.bus = &fakebus;
- fakebus.number = bus_num;
- dbg("%s: dev %d, bus %d, pin %d, num %d\n",
- __FUNCTION__, dev_num, bus_num, int_pin, irq_num);
- rc = pcibios_set_irq_routing(&fakedev, int_pin - 0x0a, irq_num);
- dbg("%s: rc %d\n", __FUNCTION__, rc);
- if (!rc)
- return !rc;
-
- /* set the Edge Level Control Register (ELCR) */
- temp_word = inb(0x4d0);
- temp_word |= inb(0x4d1) << 8;
-
- temp_word |= 0x01 << irq_num;
-
- /* This should only be for x86 as it sets the Edge Level Control Register */
- outb((u8) (temp_word & 0xFF), 0x4d0);
- outb((u8) ((temp_word & 0xFF00) >> 8), 0x4d1);
-#endif
- return 0;
-}
-
-/* More PCI configuration routines; this time centered around hotplug controller */
-
-
-/*
- * pciehp_save_config
- *
- * Reads configuration for all slots in a PCI bus and saves info.
- *
- * Note: For non-hot plug busses, the slot # saved is the device #
- *
- * returns 0 if success
- */
-int pciehp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num)
-{
- int rc;
- u8 class_code;
- u8 header_type;
- u32 ID;
- u8 secondary_bus;
- struct pci_func *new_slot;
- int sub_bus;
- int max_functions;
- int function;
- u8 DevError;
- int device = 0;
- int cloop = 0;
- int stop_it;
- int index;
- int is_hot_plug = num_ctlr_slots || first_device_num;
- struct pci_bus lpci_bus, *pci_bus;
- int FirstSupported, LastSupported;
-
- dbg("%s: Enter\n", __FUNCTION__);
-
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
-
- dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__,
- num_ctlr_slots, first_device_num);
-
- /* Decide which slots are supported */
- if (is_hot_plug) {
- /*********************************
- * is_hot_plug is the slot mask
- *********************************/
- FirstSupported = first_device_num;
- LastSupported = FirstSupported + num_ctlr_slots - 1;
- } else {
- FirstSupported = 0;
- LastSupported = 0x1F;
- }
-
- dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported,
- LastSupported);
-
- /* Save PCI configuration space for all devices in supported slots */
- dbg("%s: pci_bus->number = %x\n", __FUNCTION__, pci_bus->number);
- pci_bus->number = busnumber;
- dbg("%s: bus = %x, dev = %x\n", __FUNCTION__, busnumber, device);
- for (device = FirstSupported; device <= LastSupported; device++) {
- ID = 0xFFFFFFFF;
- rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0),
- PCI_VENDOR_ID, &ID);
-
- if (ID != 0xFFFFFFFF) { /* device in slot */
- dbg("%s: ID = %x\n", __FUNCTION__, ID);
- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
- 0x0B, &class_code);
- if (rc)
- return rc;
-
- rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0),
- PCI_HEADER_TYPE, &header_type);
- if (rc)
- return rc;
-
- dbg("class_code = %x, header_type = %x\n", class_code, header_type);
-
- /* If multi-function device, set max_functions to 8 */
- if (header_type & 0x80)
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- DevError = 0;
- dbg("%s: In do loop\n", __FUNCTION__);
-
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */
- /* Recurse the subordinate bus
- * get the subordinate bus number
- */
- rc = pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(device, function),
- PCI_SECONDARY_BUS, &secondary_bus);
- if (rc) {
- return rc;
- } else {
- sub_bus = (int) secondary_bus;
-
- /* Save secondary bus cfg spc with this recursive call. */
- rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
- if (rc)
- return rc;
- }
- }
-
- index = 0;
- new_slot = pciehp_slot_find(busnumber, device, index++);
-
- dbg("%s: new_slot = %p bus %x dev %x fun %x\n",
- __FUNCTION__, new_slot, busnumber, device, index-1);
-
- while (new_slot && (new_slot->function != (u8) function)) {
- new_slot = pciehp_slot_find(busnumber, device, index++);
- dbg("%s: while loop, new_slot = %p bus %x dev %x fun %x\n",
- __FUNCTION__, new_slot, busnumber, device, index-1);
- }
- if (!new_slot) {
- /* Setup slot structure. */
- new_slot = pciehp_slot_create(busnumber);
- dbg("%s: if, new_slot = %p bus %x dev %x fun %x\n",
- __FUNCTION__, new_slot, busnumber, device, function);
-
- if (new_slot == NULL)
- return(1);
- }
-
- new_slot->bus = (u8) busnumber;
- new_slot->device = (u8) device;
- new_slot->function = (u8) function;
- new_slot->is_a_board = 1;
- new_slot->switch_save = 0x10;
- /* In case of unsupported board */
- new_slot->status = DevError;
- new_slot->pci_dev = pci_find_slot(new_slot->bus,
- (new_slot->device << 3) | new_slot->function);
- dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev);
-
- for (cloop = 0; cloop < 0x20; cloop++) {
- rc = pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(device, function),
- cloop << 2,
- (u32 *) &(new_slot->config_space [cloop]));
- /* dbg("new_slot->config_space[%x] = %x\n",
- cloop, new_slot->config_space[cloop]); */
- if (rc)
- return rc;
- }
-
- function++;
-
- stop_it = 0;
-
- /* this loop skips to the next present function
- * reading in Class Code and Header type.
- */
-
- while ((function < max_functions)&&(!stop_it)) {
- dbg("%s: In while loop \n", __FUNCTION__);
- rc = pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(device, function),
- PCI_VENDOR_ID, &ID);
-
- if (ID == 0xFFFFFFFF) { /* nothing there. */
- function++;
- dbg("Nothing there\n");
- } else { /* Something there */
- rc = pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(device, function),
- 0x0B, &class_code);
- if (rc)
- return rc;
-
- rc = pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(device, function),
- PCI_HEADER_TYPE, &header_type);
- if (rc)
- return rc;
-
- dbg("class_code = %x, header_type = %x\n", class_code, header_type);
- stop_it++;
- }
- }
-
- } while (function < max_functions);
- /* End of IF (device in slot?) */
- } else if (is_hot_plug) {
- /* Setup slot structure with entry for empty slot */
- new_slot = pciehp_slot_create(busnumber);
-
- if (new_slot == NULL) {
- return(1);
- }
- dbg("new_slot = %p, bus = %x, dev = %x, fun = %x\n", new_slot,
- new_slot->bus, new_slot->device, new_slot->function);
-
- new_slot->bus = (u8) busnumber;
- new_slot->device = (u8) device;
- new_slot->function = 0;
- new_slot->is_a_board = 0;
- new_slot->presence_save = 0;
- new_slot->switch_save = 0;
- }
- } /* End of FOR loop */
-
- dbg("%s: Exit\n", __FUNCTION__);
- return(0);
-}
-
-
-/*
- * pciehp_save_slot_config
- *
- * Saves configuration info for all PCI devices in a given slot
- * including subordinate busses.
- *
- * returns 0 if success
- */
-int pciehp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot)
-{
- int rc;
- u8 class_code;
- u8 header_type;
- u32 ID;
- u8 secondary_bus;
- int sub_bus;
- int max_functions;
- int function;
- int cloop = 0;
- int stop_it;
- struct pci_bus lpci_bus, *pci_bus;
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = new_slot->bus;
-
- ID = 0xFFFFFFFF;
-
- pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0),
- PCI_VENDOR_ID, &ID);
-
- if (ID != 0xFFFFFFFF) { /* device in slot */
- pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
- 0x0B, &class_code);
-
- pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0),
- PCI_HEADER_TYPE, &header_type);
-
- if (header_type & 0x80) /* Multi-function device */
- max_functions = 8;
- else
- max_functions = 1;
-
- function = 0;
-
- do {
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
- /* Recurse the subordinate bus */
- pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- PCI_SECONDARY_BUS, &secondary_bus);
-
- sub_bus = (int) secondary_bus;
-
- /* Save the config headers for the secondary bus. */
- rc = pciehp_save_config(ctrl, sub_bus, 0, 0);
-
- if (rc)
- return rc;
-
- } /* End of IF */
-
- new_slot->status = 0;
-
- for (cloop = 0; cloop < 0x20; cloop++) {
- pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- cloop << 2,
- (u32 *) &(new_slot->config_space [cloop]));
- }
-
- function++;
-
- stop_it = 0;
-
- /* this loop skips to the next present function
- * reading in the Class Code and the Header type.
- */
-
- while ((function < max_functions) && (!stop_it)) {
- pci_bus_read_config_dword(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- PCI_VENDOR_ID, &ID);
-
- if (ID == 0xFFFFFFFF) { /* nothing there. */
- function++;
- } else { /* Something there */
- pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- 0x0B, &class_code);
-
- pci_bus_read_config_byte(pci_bus,
- PCI_DEVFN(new_slot->device, function),
- PCI_HEADER_TYPE, &header_type);
-
- stop_it++;
- }
- }
-
- } while (function < max_functions);
- } /* End of IF (device in slot?) */
- else {
- return 2;
- }
-
- return 0;
-}
-
-
-/*
- * pciehp_save_used_resources
- *
- * Stores used resource information for existing boards. this is
- * for boards that were in the system when this driver was loaded.
- * this function is for hot plug ADD
- *
- * returns 0 if success
- * if disable == 1(DISABLE_CARD),
- * it loops for all functions of the slot and disables them.
- * else, it just get resources of the function and return.
- */
-int pciehp_save_used_resources(struct controller *ctrl, struct pci_func *func, int disable)
-{
- u8 cloop;
- u8 header_type;
- u8 secondary_bus;
- u8 temp_byte;
- u16 command;
- u16 save_command;
- u16 w_base, w_length;
- u32 temp_register;
- u32 save_base;
- u32 base, length;
- u64 base64 = 0;
- int index = 0;
- unsigned int devfn;
- struct pci_resource *mem_node = NULL;
- struct pci_resource *p_mem_node = NULL;
- struct pci_resource *t_mem_node;
- struct pci_resource *io_node;
- struct pci_resource *bus_node;
- struct pci_bus lpci_bus, *pci_bus;
- memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
-
- if (disable)
- func = pciehp_slot_find(func->bus, func->device, index++);
-
- while ((func != NULL) && func->is_a_board) {
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- /* Save the command register */
- pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &save_command);
-
- if (disable) {
- /* disable card */
- command = 0x00;
- pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
- }
-
- /* Check for Bridge */
- pci_bus_read_config_byte(pci_bus, devfn, PCI_HEADER_TYPE, &header_type);
-
- if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */
- dbg("Save_used_res of PCI bridge b:d=0x%x:%x, sc=0x%x\n",
- func->bus, func->device, save_command);
- if (disable) {
- /* Clear Bridge Control Register */
- command = 0x00;
- pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, command);
- }
-
- pci_bus_read_config_byte(pci_bus, devfn, PCI_SECONDARY_BUS, &secondary_bus);
- pci_bus_read_config_byte(pci_bus, devfn, PCI_SUBORDINATE_BUS, &temp_byte);
-
- bus_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!bus_node)
- return -ENOMEM;
-
- bus_node->base = (ulong)secondary_bus;
- bus_node->length = (ulong)(temp_byte - secondary_bus + 1);
-
- bus_node->next = func->bus_head;
- func->bus_head = bus_node;
-
- /* Save IO base and Limit registers */
- pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_BASE, &temp_byte);
- base = temp_byte;
- pci_bus_read_config_byte(pci_bus, devfn, PCI_IO_LIMIT, &temp_byte);
- length = temp_byte;
-
- if ((base <= length) && (!disable || (save_command & PCI_COMMAND_IO))) {
- io_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!io_node)
- return -ENOMEM;
-
- io_node->base = (ulong)(base & PCI_IO_RANGE_MASK) << 8;
- io_node->length = (ulong)(length - base + 0x10) << 8;
-
- io_node->next = func->io_head;
- func->io_head = io_node;
- }
-
- /* Save memory base and Limit registers */
- pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_BASE, &w_base);
- pci_bus_read_config_word(pci_bus, devfn, PCI_MEMORY_LIMIT, &w_length);
-
- if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
- mem_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!mem_node)
- return -ENOMEM;
-
- mem_node->base = (ulong)w_base << 16;
- mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- /* Save prefetchable memory base and Limit registers */
- pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_BASE, &w_base);
- pci_bus_read_config_word(pci_bus, devfn, PCI_PREF_MEMORY_LIMIT, &w_length);
-
- if ((w_base <= w_length) && (!disable || (save_command & PCI_COMMAND_MEMORY))) {
- p_mem_node = kmalloc(sizeof(struct pci_resource),
- GFP_KERNEL);
- if (!p_mem_node)
- return -ENOMEM;
-
- p_mem_node->base = (ulong)w_base << 16;
- p_mem_node->length = (ulong)(w_length - w_base + 0x10) << 16;
-
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- }
- } else if ((header_type & 0x7F) == PCI_HEADER_TYPE_NORMAL) {
- dbg("Save_used_res of PCI adapter b:d=0x%x:%x, sc=0x%x\n",
- func->bus, func->device, save_command);
-
- /* Figure out IO and memory base lengths */
- for (cloop = PCI_BASE_ADDRESS_0; cloop <= PCI_BASE_ADDRESS_5; cloop += 4) {
- pci_bus_read_config_dword(pci_bus, devfn, cloop, &save_base);
-
- temp_register = 0xFFFFFFFF;
- pci_bus_write_config_dword(pci_bus, devfn, cloop, temp_register);
- pci_bus_read_config_dword(pci_bus, devfn, cloop, &temp_register);
-
- if (!disable)
- pci_bus_write_config_dword(pci_bus, devfn, cloop, save_base);
-
- if (!temp_register)
- continue;
-
- base = temp_register;
-
- if ((base & PCI_BASE_ADDRESS_SPACE_IO) &&
- (!disable || (save_command & PCI_COMMAND_IO))) {
- /* IO base */
- /* set temp_register = amount of IO space requested */
- base = base & 0xFFFFFFFCL;
- base = (~base) + 1;
-
- io_node = kmalloc(sizeof (struct pci_resource),
- GFP_KERNEL);
- if (!io_node)
- return -ENOMEM;
-
- io_node->base = (ulong)save_base & PCI_BASE_ADDRESS_IO_MASK;
- io_node->length = (ulong)base;
- dbg("sur adapter: IO bar=0x%x(length=0x%x)\n",
- io_node->base, io_node->length);
-
- io_node->next = func->io_head;
- func->io_head = io_node;
- } else { /* map Memory */
- int prefetchable = 1;
- /* struct pci_resources **res_node; */
- char *res_type_str = "PMEM";
- u32 temp_register2;
-
- t_mem_node = kmalloc(sizeof (struct pci_resource),
- GFP_KERNEL);
- if (!t_mem_node)
- return -ENOMEM;
-
- if (!(base & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
- (!disable || (save_command & PCI_COMMAND_MEMORY))) {
- prefetchable = 0;
- mem_node = t_mem_node;
- res_type_str++;
- } else
- p_mem_node = t_mem_node;
-
- base = base & 0xFFFFFFF0L;
- base = (~base) + 1;
-
- switch (temp_register & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
- case PCI_BASE_ADDRESS_MEM_TYPE_32:
- if (prefetchable) {
- p_mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
- p_mem_node->length = (ulong)base;
- dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
- res_type_str,
- p_mem_node->base,
- p_mem_node->length);
-
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- } else {
- mem_node->base = (ulong)save_base & PCI_BASE_ADDRESS_MEM_MASK;
- mem_node->length = (ulong)base;
- dbg("sur adapter: 32 %s bar=0x%x(length=0x%x)\n",
- res_type_str,
- mem_node->base,
- mem_node->length);
-
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- break;
- case PCI_BASE_ADDRESS_MEM_TYPE_64:
- pci_bus_read_config_dword(pci_bus, devfn, cloop+4, &temp_register2);
- base64 = temp_register2;
- base64 = (base64 << 32) | save_base;
-
- if (temp_register2) {
- dbg("sur adapter: 64 %s high dword of base64(0x%x:%x) masked to 0\n",
- res_type_str, temp_register2, (u32)base64);
- base64 &= 0x00000000FFFFFFFFL;
- }
-
- if (prefetchable) {
- p_mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
- p_mem_node->length = base;
- dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
- res_type_str,
- p_mem_node->base,
- p_mem_node->length);
-
- p_mem_node->next = func->p_mem_head;
- func->p_mem_head = p_mem_node;
- } else {
- mem_node->base = base64 & PCI_BASE_ADDRESS_MEM_MASK;
- mem_node->length = base;
- dbg("sur adapter: 64 %s base=0x%x(len=0x%x)\n",
- res_type_str,
- mem_node->base,
- mem_node->length);
-
- mem_node->next = func->mem_head;
- func->mem_head = mem_node;
- }
- cloop += 4;
- break;
- default:
- dbg("asur: reserved BAR type=0x%x\n",
- temp_register);
- break;
- }
- }
- } /* End of base register loop */
- } else { /* Some other unknown header type */
- dbg("Save_used_res of PCI unknown type b:d=0x%x:%x. skip.\n",
- func->bus, func->device);
- }
-
- /* find the next device in this slot */
- if (!disable)
- break;
- func = pciehp_slot_find(func->bus, func->device, index++);
- }
-
- return 0;
-}
-
-
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-return_resource_list(struct pci_resource **func, struct pci_resource **res)
-{
- struct pci_resource *node;
- struct pci_resource *t_node;
-
- node = *func;
- *func = NULL;
- while (node) {
- t_node = node->next;
- return_resource(res, node);
- node = t_node;
- }
-}
-
-/*
- * pciehp_return_board_resources
- *
- * this routine returns all resources allocated to a board to
- * the available pool.
- *
- * returns 0 if success
- */
-int pciehp_return_board_resources(struct pci_func * func,
- struct resource_lists * resources)
-{
- int rc;
-
- dbg("%s\n", __FUNCTION__);
-
- if (!func)
- return 1;
-
- return_resource_list(&(func->io_head),&(resources->io_head));
- return_resource_list(&(func->mem_head),&(resources->mem_head));
- return_resource_list(&(func->p_mem_head),&(resources->p_mem_head));
- return_resource_list(&(func->bus_head),&(resources->bus_head));
-
- rc = pciehp_resource_sort_and_combine(&(resources->mem_head));
- rc |= pciehp_resource_sort_and_combine(&(resources->p_mem_head));
- rc |= pciehp_resource_sort_and_combine(&(resources->io_head));
- rc |= pciehp_resource_sort_and_combine(&(resources->bus_head));
-
- return rc;
-}
-
-/**
- * kfree_resource_list: release memory of all list members
- * @res: resource list to free
- */
-static inline void
-kfree_resource_list(struct pci_resource **r)
-{
- struct pci_resource *res, *tres;
-
- res = *r;
- *r = NULL;
-
- while (res) {
- tres = res;
- res = res->next;
- kfree(tres);
- }
-}
-
-/**
- * pciehp_destroy_resource_list: put node back in the resource list
- * @resources: list to put nodes back
- */
-void pciehp_destroy_resource_list(struct resource_lists * resources)
-{
- kfree_resource_list(&(resources->io_head));
- kfree_resource_list(&(resources->mem_head));
- kfree_resource_list(&(resources->p_mem_head));
- kfree_resource_list(&(resources->bus_head));
-}
-
-/**
- * pciehp_destroy_board_resources: put node back in the resource list
- * @resources: list to put nodes back
- */
-void pciehp_destroy_board_resources(struct pci_func * func)
-{
- kfree_resource_list(&(func->io_head));
- kfree_resource_list(&(func->mem_head));
- kfree_resource_list(&(func->p_mem_head));
- kfree_resource_list(&(func->bus_head));
-}
diff --git a/drivers/pci/hotplug/pciehprm.h b/drivers/pci/hotplug/pciehprm.h
deleted file mode 100644
index 05f20fbc5f50..000000000000
--- a/drivers/pci/hotplug/pciehprm.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * PCIEHPRM : PCIEHP Resource Manager for ACPI/non-ACPI platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _PCIEHPRM_H_
-#define _PCIEHPRM_H_
-
-#ifdef CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI
-#include "pciehprm_nonacpi.h"
-#endif
-
-int pciehprm_init(enum php_ctlr_type ct);
-void pciehprm_cleanup(void);
-int pciehprm_print_pirt(void);
-int pciehprm_find_available_resources(struct controller *ctrl);
-int pciehprm_set_hpp(struct controller *ctrl, struct pci_func *func, u8 card_type);
-void pciehprm_enable_card(struct controller *ctrl, struct pci_func *func, u8 card_type);
-
-#ifdef DEBUG
-#define RES_CHECK(this, bits) \
- { if (((this) & (bits - 1))) \
- printk("%s:%d ERR: potential res loss!\n", __FUNCTION__, __LINE__); }
-#else
-#define RES_CHECK(this, bits)
-#endif
-
-#endif /* _PCIEHPRM_H_ */
diff --git a/drivers/pci/hotplug/pciehprm_acpi.c b/drivers/pci/hotplug/pciehprm_acpi.c
index 1406db35b089..ae244e218620 100644
--- a/drivers/pci/hotplug/pciehprm_acpi.c
+++ b/drivers/pci/hotplug/pciehprm_acpi.c
@@ -24,100 +24,20 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/pci.h>
-#include <linux/init.h>
#include <linux/acpi.h>
-#include <linux/efi.h>
#include <linux/pci-acpi.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
-#include <acpi/acpi.h>
#include <acpi/acpi_bus.h>
#include <acpi/actypes.h>
#include "pciehp.h"
-#include "pciehprm.h"
-
-#define PCI_MAX_BUS 0x100
-#define ACPI_STA_DEVICE_PRESENT 0x01
#define METHOD_NAME__SUN "_SUN"
#define METHOD_NAME__HPP "_HPP"
#define METHOD_NAME_OSHP "OSHP"
-/* Status code for running acpi method to gain native control */
-#define NC_NOT_RUN 0
-#define OSC_NOT_EXIST 1
-#define OSC_RUN_FAILED 2
-#define OSHP_NOT_EXIST 3
-#define OSHP_RUN_FAILED 4
-#define NC_RUN_SUCCESS 5
-
-#define PHP_RES_BUS 0xA0
-#define PHP_RES_IO 0xA1
-#define PHP_RES_MEM 0xA2
-#define PHP_RES_PMEM 0xA3
-
-#define BRIDGE_TYPE_P2P 0x00
-#define BRIDGE_TYPE_HOST 0x01
-
-/* this should go to drivers/acpi/include/ */
-struct acpi__hpp {
- u8 cache_line_size;
- u8 latency_timer;
- u8 enable_serr;
- u8 enable_perr;
-};
-
-struct acpi_php_slot {
- struct acpi_php_slot *next;
- struct acpi_bridge *bridge;
- acpi_handle handle;
- int seg;
- int bus;
- int dev;
- int fun;
- u32 sun;
- struct pci_resource *mem_head;
- struct pci_resource *p_mem_head;
- struct pci_resource *io_head;
- struct pci_resource *bus_head;
- void *slot_ops; /* _STA, _EJx, etc */
- struct slot *slot;
-}; /* per func */
-
-struct acpi_bridge {
- struct acpi_bridge *parent;
- struct acpi_bridge *next;
- struct acpi_bridge *child;
- acpi_handle handle;
- int seg;
- int pbus; /* pdev->bus->number */
- int pdevice; /* PCI_SLOT(pdev->devfn) */
- int pfunction; /* PCI_DEVFN(pdev->devfn) */
- int bus; /* pdev->subordinate->number */
- struct acpi__hpp *_hpp;
- struct acpi_php_slot *slots;
- struct pci_resource *tmem_head; /* total from crs */
- struct pci_resource *tp_mem_head; /* total from crs */
- struct pci_resource *tio_head; /* total from crs */
- struct pci_resource *tbus_head; /* total from crs */
- struct pci_resource *mem_head; /* available */
- struct pci_resource *p_mem_head; /* available */
- struct pci_resource *io_head; /* available */
- struct pci_resource *bus_head; /* available */
- int scanned;
- int type;
-};
-
-static struct acpi_bridge *acpi_bridges_head;
-
static u8 * acpi_path_name( acpi_handle handle)
{
acpi_status status;
@@ -133,85 +53,43 @@ static u8 * acpi_path_name( acpi_handle handle)
return path_name;
}
-static void acpi_get__hpp ( struct acpi_bridge *ab);
-static int acpi_run_oshp ( struct acpi_bridge *ab);
-static int osc_run_status = NC_NOT_RUN;
-static int oshp_run_status = NC_NOT_RUN;
-
-static int acpi_add_slot_to_php_slots(
- struct acpi_bridge *ab,
- int bus_num,
- acpi_handle handle,
- u32 adr,
- u32 sun
- )
-{
- struct acpi_php_slot *aps;
- static long samesun = -1;
-
- aps = (struct acpi_php_slot *) kmalloc (sizeof(struct acpi_php_slot), GFP_KERNEL);
- if (!aps) {
- err ("acpi_pciehprm: alloc for aps fail\n");
- return -1;
- }
- memset(aps, 0, sizeof(struct acpi_php_slot));
-
- aps->handle = handle;
- aps->bus = bus_num;
- aps->dev = (adr >> 16) & 0xffff;
- aps->fun = adr & 0xffff;
- aps->sun = sun;
-
- aps->next = ab->slots; /* cling to the bridge */
- aps->bridge = ab;
- ab->slots = aps;
-
- ab->scanned += 1;
- if (!ab->_hpp)
- acpi_get__hpp(ab);
-
- if (osc_run_status == OSC_NOT_EXIST)
- oshp_run_status = acpi_run_oshp(ab);
-
- if (sun != samesun) {
- info("acpi_pciehprm: Slot sun(%x) at s:b:d:f=0x%02x:%02x:%02x:%02x\n",
- aps->sun, ab->seg, aps->bus, aps->dev, aps->fun);
- samesun = sun;
- }
- return 0;
-}
-
-static void acpi_get__hpp ( struct acpi_bridge *ab)
+static acpi_status
+acpi_run_hpp(acpi_handle handle, struct hotplug_params *hpp)
{
acpi_status status;
u8 nui[4];
struct acpi_buffer ret_buf = { 0, NULL};
union acpi_object *ext_obj, *package;
- u8 *path_name = acpi_path_name(ab->handle);
+ u8 *path_name = acpi_path_name(handle);
int i, len = 0;
/* get _hpp */
- status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP, NULL, &ret_buf);
switch (status) {
case AE_BUFFER_OVERFLOW:
ret_buf.pointer = kmalloc (ret_buf.length, GFP_KERNEL);
if (!ret_buf.pointer) {
- err ("acpi_pciehprm:%s alloc for _HPP fail\n", path_name);
- return;
+ err ("%s:%s alloc for _HPP fail\n", __FUNCTION__,
+ path_name);
+ return AE_NO_MEMORY;
}
- status = acpi_evaluate_object(ab->handle, METHOD_NAME__HPP, NULL, &ret_buf);
+ status = acpi_evaluate_object(handle, METHOD_NAME__HPP,
+ NULL, &ret_buf);
if (ACPI_SUCCESS(status))
break;
default:
if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s _HPP fail=0x%x\n", path_name, status);
- return;
+ dbg("%s:%s _HPP fail=0x%x\n", __FUNCTION__,
+ path_name, status);
+ return status;
}
}
ext_obj = (union acpi_object *) ret_buf.pointer;
if (ext_obj->type != ACPI_TYPE_PACKAGE) {
- err ("acpi_pciehprm:%s _HPP obj not a package\n", path_name);
+ err ("%s:%s _HPP obj not a package\n", __FUNCTION__,
+ path_name);
+ status = AE_ERROR;
goto free_and_return;
}
@@ -224,1514 +102,153 @@ static void acpi_get__hpp ( struct acpi_bridge *ab)
nui[i] = (u8)ext_obj->integer.value;
break;
default:
- err ("acpi_pciehprm:%s _HPP obj type incorrect\n", path_name);
+ err ("%s:%s _HPP obj type incorrect\n", __FUNCTION__,
+ path_name);
+ status = AE_ERROR;
goto free_and_return;
}
}
- ab->_hpp = kmalloc (sizeof (struct acpi__hpp), GFP_KERNEL);
- if (!ab->_hpp) {
- err ("acpi_pciehprm:%s alloc for _HPP failed\n", path_name);
- goto free_and_return;
- }
- memset(ab->_hpp, 0, sizeof(struct acpi__hpp));
+ hpp->cache_line_size = nui[0];
+ hpp->latency_timer = nui[1];
+ hpp->enable_serr = nui[2];
+ hpp->enable_perr = nui[3];
- ab->_hpp->cache_line_size = nui[0];
- ab->_hpp->latency_timer = nui[1];
- ab->_hpp->enable_serr = nui[2];
- ab->_hpp->enable_perr = nui[3];
-
- dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr);
+ dbg(" _HPP: cache_line_size=0x%x\n", hpp->cache_line_size);
+ dbg(" _HPP: latency timer =0x%x\n", hpp->latency_timer);
+ dbg(" _HPP: enable SERR =0x%x\n", hpp->enable_serr);
+ dbg(" _HPP: enable PERR =0x%x\n", hpp->enable_perr);
free_and_return:
kfree(ret_buf.pointer);
+ return status;
}
-static int acpi_run_oshp ( struct acpi_bridge *ab)
+static acpi_status acpi_run_oshp(acpi_handle handle)
{
acpi_status status;
- u8 *path_name = acpi_path_name(ab->handle);
+ u8 *path_name = acpi_path_name(handle);
/* run OSHP */
- status = acpi_evaluate_object(ab->handle, METHOD_NAME_OSHP, NULL, NULL);
+ status = acpi_evaluate_object(handle, METHOD_NAME_OSHP, NULL, NULL);
if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s OSHP fails=0x%x\n", path_name, status);
- oshp_run_status = (status == AE_NOT_FOUND) ? OSHP_NOT_EXIST : OSHP_RUN_FAILED;
+ dbg("%s:%s OSHP fails=0x%x\n", __FUNCTION__, path_name,
+ status);
} else {
- oshp_run_status = NC_RUN_SUCCESS;
- dbg("acpi_pciehprm:%s OSHP passes =0x%x\n", path_name, status);
- dbg("acpi_pciehprm:%s oshp_run_status =0x%x\n", path_name, oshp_run_status);
- }
- return oshp_run_status;
-}
-
-static acpi_status acpi_evaluate_crs(
- acpi_handle handle,
- struct acpi_resource **retbuf
- )
-{
- acpi_status status;
- struct acpi_buffer crsbuf;
- u8 *path_name = acpi_path_name(handle);
-
- crsbuf.length = 0;
- crsbuf.pointer = NULL;
-
- status = acpi_get_current_resources (handle, &crsbuf);
-
- switch (status) {
- case AE_BUFFER_OVERFLOW:
- break; /* found */
- case AE_NOT_FOUND:
- dbg("acpi_pciehprm:%s _CRS not found\n", path_name);
- return status;
- default:
- err ("acpi_pciehprm:%s _CRS fail=0x%x\n", path_name, status);
- return status;
+ dbg("%s:%s OSHP passes\n", __FUNCTION__, path_name);
}
-
- crsbuf.pointer = kmalloc (crsbuf.length, GFP_KERNEL);
- if (!crsbuf.pointer) {
- err ("acpi_pciehprm: alloc %ld bytes for %s _CRS fail\n", (ulong)crsbuf.length, path_name);
- return AE_NO_MEMORY;
- }
-
- status = acpi_get_current_resources (handle, &crsbuf);
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm: %s _CRS fail=0x%x.\n", path_name, status);
- kfree(crsbuf.pointer);
- return status;
- }
-
- *retbuf = crsbuf.pointer;
-
return status;
}
-static void free_pci_resource ( struct pci_resource *aprh)
+static int is_root_bridge(acpi_handle handle)
{
- struct pci_resource *res, *next;
+ acpi_status status;
+ struct acpi_device_info *info;
+ struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
+ int i;
- for (res = aprh; res; res = next) {
- next = res->next;
- kfree(res);
- }
-}
-
-static void print_pci_resource ( struct pci_resource *aprh)
-{
- struct pci_resource *res;
-
- for (res = aprh; res; res = res->next)
- dbg(" base= 0x%x length= 0x%x\n", res->base, res->length);
-}
-
-static void print_slot_resources( struct acpi_php_slot *aps)
-{
- if (aps->bus_head) {
- dbg(" BUS Resources:\n");
- print_pci_resource (aps->bus_head);
- }
-
- if (aps->io_head) {
- dbg(" IO Resources:\n");
- print_pci_resource (aps->io_head);
- }
-
- if (aps->mem_head) {
- dbg(" MEM Resources:\n");
- print_pci_resource (aps->mem_head);
- }
-
- if (aps->p_mem_head) {
- dbg(" PMEM Resources:\n");
- print_pci_resource (aps->p_mem_head);
- }
-}
-
-static void print_pci_resources( struct acpi_bridge *ab)
-{
- if (ab->tbus_head) {
- dbg(" Total BUS Resources:\n");
- print_pci_resource (ab->tbus_head);
- }
- if (ab->bus_head) {
- dbg(" BUS Resources:\n");
- print_pci_resource (ab->bus_head);
- }
-
- if (ab->tio_head) {
- dbg(" Total IO Resources:\n");
- print_pci_resource (ab->tio_head);
- }
- if (ab->io_head) {
- dbg(" IO Resources:\n");
- print_pci_resource (ab->io_head);
- }
-
- if (ab->tmem_head) {
- dbg(" Total MEM Resources:\n");
- print_pci_resource (ab->tmem_head);
- }
- if (ab->mem_head) {
- dbg(" MEM Resources:\n");
- print_pci_resource (ab->mem_head);
- }
-
- if (ab->tp_mem_head) {
- dbg(" Total PMEM Resources:\n");
- print_pci_resource (ab->tp_mem_head);
- }
- if (ab->p_mem_head) {
- dbg(" PMEM Resources:\n");
- print_pci_resource (ab->p_mem_head);
- }
- if (ab->_hpp) {
- dbg(" _HPP: cache_line_size=0x%x\n", ab->_hpp->cache_line_size);
- dbg(" _HPP: latency timer =0x%x\n", ab->_hpp->latency_timer);
- dbg(" _HPP: enable SERR =0x%x\n", ab->_hpp->enable_serr);
- dbg(" _HPP: enable PERR =0x%x\n", ab->_hpp->enable_perr);
- }
-}
-
-static int pciehprm_delete_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
- struct pci_resource *prevnode;
- struct pci_resource *split_node;
- ulong tbase;
-
- pciehp_resource_sort_and_combine(aprh);
-
- for (res = *aprh; res; res = res->next) {
- if (res->base > base)
- continue;
-
- if ((res->base + res->length) < (base + size))
- continue;
-
- if (res->base < base) {
- tbase = base;
-
- if ((res->length - (tbase - res->base)) < size)
- continue;
-
- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base;
- split_node->length = tbase - res->base;
- res->base = tbase;
- res->length -= split_node->length;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (res->length >= size) {
- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base + size;
- split_node->length = res->length - size;
- res->length = size;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (*aprh == res) {
- *aprh = res->next;
- } else {
- prevnode = *aprh;
- while (prevnode->next != res)
- prevnode = prevnode->next;
-
- prevnode->next = res->next;
- }
- res->next = NULL;
- kfree(res);
- break;
- }
-
- return 0;
-}
-
-static int pciehprm_delete_resources(
- struct pci_resource **aprh,
- struct pci_resource *this
- )
-{
- struct pci_resource *res;
-
- for (res = this; res; res = res->next)
- pciehprm_delete_resource(aprh, res->base, res->length);
-
- return 0;
-}
-
-static int pciehprm_add_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
-
- for (res = *aprh; res; res = res->next) {
- if ((res->base + res->length) == base) {
- res->length += size;
- size = 0L;
- break;
+ status = acpi_get_object_info(handle, &buffer);
+ if (ACPI_SUCCESS(status)) {
+ info = buffer.pointer;
+ if ((info->valid & ACPI_VALID_HID) &&
+ !strcmp(PCI_ROOT_HID_STRING,
+ info->hardware_id.value)) {
+ acpi_os_free(buffer.pointer);
+ return 1;
+ }
+ if (info->valid & ACPI_VALID_CID) {
+ for (i=0; i < info->compatibility_id.count; i++) {
+ if (!strcmp(PCI_ROOT_HID_STRING,
+ info->compatibility_id.id[i].value)) {
+ acpi_os_free(buffer.pointer);
+ return 1;
+ }
+ }
}
- if (res->next == *aprh)
- break;
}
-
- if (size) {
- res = kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!res) {
- err ("acpi_pciehprm: alloc for res fail\n");
- return -ENOMEM;
- }
- memset(res, 0, sizeof (struct pci_resource));
-
- res->base = base;
- res->length = size;
- res->next = *aprh;
- *aprh = res;
- }
-
return 0;
}
-static int pciehprm_add_resources(
- struct pci_resource **aprh,
- struct pci_resource *this
- )
-{
- struct pci_resource *res;
- int rc = 0;
-
- for (res = this; res && !rc; res = res->next)
- rc = pciehprm_add_resource(aprh, res->base, res->length);
-
- return rc;
-}
-
-static void acpi_parse_io (
- struct acpi_bridge *ab,
- union acpi_resource_data *data
- )
+int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
- struct acpi_resource_io *dataio;
- dataio = (struct acpi_resource_io *) data;
-
- dbg("Io Resource\n");
- dbg(" %d bit decode\n", ACPI_DECODE_16 == dataio->io_decode ? 16:10);
- dbg(" Range minimum base: %08X\n", dataio->min_base_address);
- dbg(" Range maximum base: %08X\n", dataio->max_base_address);
- dbg(" Alignment: %08X\n", dataio->alignment);
- dbg(" Range Length: %08X\n", dataio->range_length);
-}
-
-static void acpi_parse_fixed_io (
- struct acpi_bridge *ab,
- union acpi_resource_data *data
- )
-{
- struct acpi_resource_fixed_io *datafio;
- datafio = (struct acpi_resource_fixed_io *) data;
-
- dbg("Fixed Io Resource\n");
- dbg(" Range base address: %08X", datafio->base_address);
- dbg(" Range length: %08X", datafio->range_length);
-}
-
-static void acpi_parse_address16_32 (
- struct acpi_bridge *ab,
- union acpi_resource_data *data,
- acpi_resource_type id
- )
-{
- /*
- * acpi_resource_address16 == acpi_resource_address32
- * acpi_resource_address16 *data16 = (acpi_resource_address16 *) data;
+ acpi_status status;
+ acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev));
+ struct pci_dev *pdev = dev;
+ u8 *path_name;
+ /*
+ * Per PCI firmware specification, we should run the ACPI _OSC
+ * method to get control of hotplug hardware before using it.
+ * If an _OSC is missing, we look for an OSHP to do the same thing.
+ * To handle different BIOS behavior, we look for _OSC and OSHP
+ * within the scope of the hotplug controller and its parents, upto
+ * the host bridge under which this controller exists.
*/
- struct acpi_resource_address32 *data32 = (struct acpi_resource_address32 *) data;
- struct pci_resource **aprh, **tprh;
-
- if (id == ACPI_RSTYPE_ADDRESS16)
- dbg("acpi_pciehprm:16-Bit Address Space Resource\n");
- else
- dbg("acpi_pciehprm:32-Bit Address Space Resource\n");
-
- switch (data32->resource_type) {
- case ACPI_MEMORY_RANGE:
- dbg(" Resource Type: Memory Range\n");
- aprh = &ab->mem_head;
- tprh = &ab->tmem_head;
-
- switch (data32->attribute.memory.cache_attribute) {
- case ACPI_NON_CACHEABLE_MEMORY:
- dbg(" Type Specific: Noncacheable memory\n");
- break;
- case ACPI_CACHABLE_MEMORY:
- dbg(" Type Specific: Cacheable memory\n");
- break;
- case ACPI_WRITE_COMBINING_MEMORY:
- dbg(" Type Specific: Write-combining memory\n");
- break;
- case ACPI_PREFETCHABLE_MEMORY:
- aprh = &ab->p_mem_head;
- dbg(" Type Specific: Prefetchable memory\n");
- break;
- default:
- dbg(" Type Specific: Invalid cache attribute\n");
+ while (!handle) {
+ /*
+ * This hotplug controller was not listed in the ACPI name
+ * space at all. Try to get acpi handle of parent pci bus.
+ */
+ if (!pdev || !pdev->bus->parent)
break;
- }
-
- dbg(" Type Specific: Read%s\n", ACPI_READ_WRITE_MEMORY == data32->attribute.memory.read_write_attribute ? "/Write":" Only");
- break;
-
- case ACPI_IO_RANGE:
- dbg(" Resource Type: I/O Range\n");
- aprh = &ab->io_head;
- tprh = &ab->tio_head;
-
- switch (data32->attribute.io.range_attribute) {
- case ACPI_NON_ISA_ONLY_RANGES:
- dbg(" Type Specific: Non-ISA Io Addresses\n");
- break;
- case ACPI_ISA_ONLY_RANGES:
- dbg(" Type Specific: ISA Io Addresses\n");
- break;
- case ACPI_ENTIRE_RANGE:
- dbg(" Type Specific: ISA and non-ISA Io Addresses\n");
- break;
- default:
- dbg(" Type Specific: Invalid range attribute\n");
+ dbg("Could not find %s in acpi namespace, trying parent\n",
+ pci_name(pdev));
+ if (!pdev->bus->parent->self)
+ /* Parent must be a host bridge */
+ handle = acpi_get_pci_rootbridge_handle(
+ pci_domain_nr(pdev->bus->parent),
+ pdev->bus->parent->number);
+ else
+ handle = DEVICE_ACPI_HANDLE(
+ &(pdev->bus->parent->self->dev));
+ pdev = pdev->bus->parent->self;
+ }
+
+ while (handle) {
+ path_name = acpi_path_name(handle);
+ dbg("Trying to get hotplug control for %s \n", path_name);
+ status = pci_osc_control_set(handle,
+ OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
+ if (status == AE_NOT_FOUND)
+ status = acpi_run_oshp(handle);
+ if (ACPI_SUCCESS(status)) {
+ dbg("Gained control for hotplug HW for pci %s (%s)\n",
+ pci_name(dev), path_name);
+ return 0;
+ }
+ if (is_root_bridge(handle))
break;
- }
- break;
-
- case ACPI_BUS_NUMBER_RANGE:
- dbg(" Resource Type: Bus Number Range(fixed)\n");
- /* fixup to be compatible with the rest of php driver */
- data32->min_address_range++;
- data32->address_length--;
- aprh = &ab->bus_head;
- tprh = &ab->tbus_head;
- break;
- default:
- dbg(" Resource Type: Invalid resource type. Exiting.\n");
- return;
- }
-
- dbg(" Resource %s\n", ACPI_CONSUMER == data32->producer_consumer ? "Consumer":"Producer");
- dbg(" %s decode\n", ACPI_SUB_DECODE == data32->decode ? "Subtractive":"Positive");
- dbg(" Min address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->min_address_fixed ? "":"not");
- dbg(" Max address is %s fixed\n", ACPI_ADDRESS_FIXED == data32->max_address_fixed ? "":"not");
- dbg(" Granularity: %08X\n", data32->granularity);
- dbg(" Address range min: %08X\n", data32->min_address_range);
- dbg(" Address range max: %08X\n", data32->max_address_range);
- dbg(" Address translation offset: %08X\n", data32->address_translation_offset);
- dbg(" Address Length: %08X\n", data32->address_length);
-
- if (0xFF != data32->resource_source.index) {
- dbg(" Resource Source Index: %X\n", data32->resource_source.index);
- /* dbg(" Resource Source: %s\n", data32->resource_source.string_ptr); */
- }
-
- pciehprm_add_resource(aprh, data32->min_address_range, data32->address_length);
-}
-
-static acpi_status acpi_parse_crs(
- struct acpi_bridge *ab,
- struct acpi_resource *crsbuf
- )
-{
- acpi_status status = AE_OK;
- struct acpi_resource *resource = crsbuf;
- u8 count = 0;
- u8 done = 0;
-
- while (!done) {
- dbg("acpi_pciehprm: PCI bus 0x%x Resource structure %x.\n", ab->bus, count++);
- switch (resource->id) {
- case ACPI_RSTYPE_IRQ:
- dbg("Irq -------- Resource\n");
- break;
- case ACPI_RSTYPE_DMA:
- dbg("DMA -------- Resource\n");
- break;
- case ACPI_RSTYPE_START_DPF:
- dbg("Start DPF -------- Resource\n");
- break;
- case ACPI_RSTYPE_END_DPF:
- dbg("End DPF -------- Resource\n");
- break;
- case ACPI_RSTYPE_IO:
- acpi_parse_io (ab, &resource->data);
- break;
- case ACPI_RSTYPE_FIXED_IO:
- acpi_parse_fixed_io (ab, &resource->data);
- break;
- case ACPI_RSTYPE_VENDOR:
- dbg("Vendor -------- Resource\n");
- break;
- case ACPI_RSTYPE_END_TAG:
- dbg("End_tag -------- Resource\n");
- done = 1;
- break;
- case ACPI_RSTYPE_MEM24:
- dbg("Mem24 -------- Resource\n");
- break;
- case ACPI_RSTYPE_MEM32:
- dbg("Mem32 -------- Resource\n");
- break;
- case ACPI_RSTYPE_FIXED_MEM32:
- dbg("Fixed Mem32 -------- Resource\n");
- break;
- case ACPI_RSTYPE_ADDRESS16:
- acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS16);
- break;
- case ACPI_RSTYPE_ADDRESS32:
- acpi_parse_address16_32(ab, &resource->data, ACPI_RSTYPE_ADDRESS32);
- break;
- case ACPI_RSTYPE_ADDRESS64:
- info("Address64 -------- Resource unparsed\n");
- break;
- case ACPI_RSTYPE_EXT_IRQ:
- dbg("Ext Irq -------- Resource\n");
- break;
- default:
- dbg("Invalid -------- resource type 0x%x\n", resource->id);
- break;
- }
-
- resource = (struct acpi_resource *) ((char *)resource + resource->length);
- }
-
- return status;
-}
-
-static acpi_status acpi_get_crs( struct acpi_bridge *ab)
-{
- acpi_status status;
- struct acpi_resource *crsbuf;
-
- status = acpi_evaluate_crs(ab->handle, &crsbuf);
- if (ACPI_SUCCESS(status)) {
- status = acpi_parse_crs(ab, crsbuf);
- kfree(crsbuf);
-
- pciehp_resource_sort_and_combine(&ab->bus_head);
- pciehp_resource_sort_and_combine(&ab->io_head);
- pciehp_resource_sort_and_combine(&ab->mem_head);
- pciehp_resource_sort_and_combine(&ab->p_mem_head);
-
- pciehprm_add_resources (&ab->tbus_head, ab->bus_head);
- pciehprm_add_resources (&ab->tio_head, ab->io_head);
- pciehprm_add_resources (&ab->tmem_head, ab->mem_head);
- pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
- }
-
- return status;
-}
-
-/* find acpi_bridge downword from ab. */
-static struct acpi_bridge *
-find_acpi_bridge_by_bus(
- struct acpi_bridge *ab,
- int seg,
- int bus /* pdev->subordinate->number */
- )
-{
- struct acpi_bridge *lab = NULL;
-
- if (!ab)
- return NULL;
-
- if ((ab->bus == bus) && (ab->seg == seg))
- return ab;
-
- if (ab->child)
- lab = find_acpi_bridge_by_bus(ab->child, seg, bus);
-
- if (!lab)
- if (ab->next)
- lab = find_acpi_bridge_by_bus(ab->next, seg, bus);
-
- return lab;
-}
-
-/*
- * Build a device tree of ACPI PCI Bridges
- */
-static void pciehprm_acpi_register_a_bridge (
- struct acpi_bridge **head,
- struct acpi_bridge *pab, /* parent bridge to which child bridge is added */
- struct acpi_bridge *cab /* child bridge to add */
- )
-{
- struct acpi_bridge *lpab;
- struct acpi_bridge *lcab;
-
- lpab = find_acpi_bridge_by_bus(*head, pab->seg, pab->bus);
- if (!lpab) {
- if (!(pab->type & BRIDGE_TYPE_HOST))
- warn("PCI parent bridge s:b(%x:%x) not in list.\n", pab->seg, pab->bus);
- pab->next = *head;
- *head = pab;
- lpab = pab;
- }
-
- if ((cab->type & BRIDGE_TYPE_HOST) && (pab == cab))
- return;
-
- lcab = find_acpi_bridge_by_bus(*head, cab->seg, cab->bus);
- if (lcab) {
- if ((pab->bus != lcab->parent->bus) || (lcab->bus != cab->bus))
- err("PCI child bridge s:b(%x:%x) in list with diff parent.\n", cab->seg, cab->bus);
- return;
- } else
- lcab = cab;
-
- lcab->parent = lpab;
- lcab->next = lpab->child;
- lpab->child = lcab;
-}
-
-static acpi_status pciehprm_acpi_build_php_slots_callback(
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval
- )
-{
- ulong bus_num;
- ulong seg_num;
- ulong sun, adr;
- ulong padr = 0;
- acpi_handle phandle = NULL;
- struct acpi_bridge *pab = (struct acpi_bridge *)context;
- struct acpi_bridge *lab;
- acpi_status status;
- u8 *path_name = acpi_path_name(handle);
-
- /* get _SUN */
- status = acpi_evaluate_integer(handle, METHOD_NAME__SUN, NULL, &sun);
- switch(status) {
- case AE_NOT_FOUND:
- return AE_OK;
- default:
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s _SUN fail=0x%x\n", path_name, status);
- return status;
- }
- }
-
- /* get _ADR. _ADR must exist if _SUN exists */
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
- return status;
- }
-
- dbg("acpi_pciehprm:%s sun=0x%08x adr=0x%08x\n", path_name, (u32)sun, (u32)adr);
-
- status = acpi_get_parent(handle, &phandle);
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s get_parent fail=0x%x\n", path_name, status);
- return (status);
- }
-
- bus_num = pab->bus;
- seg_num = pab->seg;
-
- if (pab->bus == bus_num) {
- lab = pab;
- } else {
- dbg("WARN: pab is not parent\n");
- lab = find_acpi_bridge_by_bus(pab, seg_num, bus_num);
- if (!lab) {
- dbg("acpi_pciehprm: alloc new P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
- lab = (struct acpi_bridge *)kmalloc(sizeof(struct acpi_bridge), GFP_KERNEL);
- if (!lab) {
- err("acpi_pciehprm: alloc for ab fail\n");
- return AE_NO_MEMORY;
- }
- memset(lab, 0, sizeof(struct acpi_bridge));
-
- lab->handle = phandle;
- lab->pbus = pab->bus;
- lab->pdevice = (int)(padr >> 16) & 0xffff;
- lab->pfunction = (int)(padr & 0xffff);
- lab->bus = (int)bus_num;
- lab->scanned = 0;
- lab->type = BRIDGE_TYPE_P2P;
-
- pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, lab);
- } else
- dbg("acpi_pciehprm: found P2P bridge(%x) for sun(%08x)\n", (u32)bus_num, (u32)sun);
- }
-
- acpi_add_slot_to_php_slots(lab, (int)bus_num, handle, (u32)adr, (u32)sun);
-
- return (status);
-}
-
-static int pciehprm_acpi_build_php_slots(
- struct acpi_bridge *ab,
- u32 depth
- )
-{
- acpi_status status;
- u8 *path_name = acpi_path_name(ab->handle);
-
- /* Walk down this pci bridge to get _SUNs if any behind P2P */
- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
- ab->handle,
- depth,
- pciehprm_acpi_build_php_slots_callback,
- ab,
- NULL );
- if (ACPI_FAILURE(status)) {
- dbg("acpi_pciehprm:%s walk for _SUN on pci bridge seg:bus(%x:%x) fail=0x%x\n", path_name, ab->seg, ab->bus, status);
- return -1;
- }
-
- return 0;
-}
-
-static void build_a_bridge(
- struct acpi_bridge *pab,
- struct acpi_bridge *ab
- )
-{
- u8 *path_name = acpi_path_name(ab->handle);
-
- pciehprm_acpi_register_a_bridge (&acpi_bridges_head, pab, ab);
-
- switch (ab->type) {
- case BRIDGE_TYPE_HOST:
- dbg("acpi_pciehprm: Registered PCI HOST Bridge(%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
- ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
- break;
- case BRIDGE_TYPE_P2P:
- dbg("acpi_pciehprm: Registered PCI P2P Bridge(%02x-%02x) on s:b:d:f(%02x:%02x:%02x:%02x) [%s]\n",
- ab->pbus, ab->bus, ab->seg, ab->pbus, ab->pdevice, ab->pfunction, path_name);
- break;
- };
-
- /* build any immediate PHP slots under this pci bridge */
- pciehprm_acpi_build_php_slots(ab, 1);
-}
-
-static struct acpi_bridge * add_p2p_bridge(
- acpi_handle handle,
- struct acpi_bridge *pab, /* parent */
- ulong adr
- )
-{
- struct acpi_bridge *ab;
- struct pci_dev *pdev;
- ulong devnum, funcnum;
- u8 *path_name = acpi_path_name(handle);
-
- ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
- if (!ab) {
- err("acpi_pciehprm: alloc for ab fail\n");
- return NULL;
- }
- memset(ab, 0, sizeof(struct acpi_bridge));
-
- devnum = (adr >> 16) & 0xffff;
- funcnum = adr & 0xffff;
-
- pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
- if (!pdev || !pdev->subordinate) {
- err("acpi_pciehprm:%s is not a P2P Bridge\n", path_name);
- kfree(ab);
- return NULL;
- }
-
- ab->handle = handle;
- ab->seg = pab->seg;
- ab->pbus = pab->bus; /* or pdev->bus->number */
- ab->pdevice = devnum; /* or PCI_SLOT(pdev->devfn) */
- ab->pfunction = funcnum; /* or PCI_FUNC(pdev->devfn) */
- ab->bus = pdev->subordinate->number;
- ab->scanned = 0;
- ab->type = BRIDGE_TYPE_P2P;
-
- dbg("acpi_pciehprm: P2P(%x-%x) on pci=b:d:f(%x:%x:%x) acpi=b:d:f(%x:%x:%x) [%s]\n",
- pab->bus, ab->bus, pdev->bus->number, PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
- pab->bus, (u32)devnum, (u32)funcnum, path_name);
-
- build_a_bridge(pab, ab);
-
- return ab;
-}
-
-static acpi_status scan_p2p_bridge(
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval
- )
-{
- struct acpi_bridge *pab = (struct acpi_bridge *)context;
- struct acpi_bridge *ab;
- acpi_status status;
- ulong adr = 0;
- u8 *path_name = acpi_path_name(handle);
- ulong devnum, funcnum;
- struct pci_dev *pdev;
-
- /* get device, function */
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- if (status != AE_NOT_FOUND)
- err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
- return AE_OK;
- }
-
- devnum = (adr >> 16) & 0xffff;
- funcnum = adr & 0xffff;
-
- pdev = pci_find_slot(pab->bus, PCI_DEVFN(devnum, funcnum));
- if (!pdev)
- return AE_OK;
- if (!pdev->subordinate)
- return AE_OK;
-
- ab = add_p2p_bridge(handle, pab, adr);
- if (ab) {
- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
- handle,
- (u32)1,
- scan_p2p_bridge,
- ab,
- NULL);
+ chandle = handle;
+ status = acpi_get_parent(chandle, &handle);
if (ACPI_FAILURE(status))
- dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status);
- }
-
- return AE_OK;
-}
-
-static struct acpi_bridge * add_host_bridge(
- acpi_handle handle,
- ulong segnum,
- ulong busnum
- )
-{
- ulong adr = 0;
- acpi_status status;
- struct acpi_bridge *ab;
- u8 *path_name = acpi_path_name(handle);
-
- /* get device, function: host br adr is always 0000 though. */
- status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL, &adr);
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s _ADR fail=0x%x\n", path_name, status);
- return NULL;
- }
- dbg("acpi_pciehprm: ROOT PCI seg(0x%x)bus(0x%x)dev(0x%x)func(0x%x) [%s]\n", (u32)segnum,
- (u32)busnum, (u32)(adr >> 16) & 0xffff, (u32)adr & 0xffff, path_name);
-
- ab = (struct acpi_bridge *) kmalloc (sizeof(struct acpi_bridge), GFP_KERNEL);
- if (!ab) {
- err("acpi_pciehprm: alloc for ab fail\n");
- return NULL;
- }
- memset(ab, 0, sizeof(struct acpi_bridge));
-
- ab->handle = handle;
- ab->seg = (int)segnum;
- ab->bus = ab->pbus = (int)busnum;
- ab->pdevice = (int)(adr >> 16) & 0xffff;
- ab->pfunction = (int)(adr & 0xffff);
- ab->scanned = 0;
- ab->type = BRIDGE_TYPE_HOST;
-
- /* get root pci bridge's current resources */
- status = acpi_get_crs(ab);
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s evaluate _CRS fail=0x%x\n", path_name, status);
- kfree(ab);
- return NULL;
- }
-
- status = pci_osc_control_set (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL);
- if (ACPI_FAILURE(status)) {
- err("%s: status %x\n", __FUNCTION__, status);
- osc_run_status = (status == AE_NOT_FOUND) ? OSC_NOT_EXIST : OSC_RUN_FAILED;
- } else {
- osc_run_status = NC_RUN_SUCCESS;
- }
- dbg("%s: osc_run_status %x\n", __FUNCTION__, osc_run_status);
-
- build_a_bridge(ab, ab);
-
- return ab;
-}
-
-static acpi_status acpi_scan_from_root_pci_callback (
- acpi_handle handle,
- u32 Level,
- void *context,
- void **retval
- )
-{
- ulong segnum = 0;
- ulong busnum = 0;
- acpi_status status;
- struct acpi_bridge *ab;
- u8 *path_name = acpi_path_name(handle);
-
- /* get bus number of this pci root bridge */
- status = acpi_evaluate_integer(handle, METHOD_NAME__SEG, NULL, &segnum);
- if (ACPI_FAILURE(status)) {
- if (status != AE_NOT_FOUND) {
- err("acpi_pciehprm:%s evaluate _SEG fail=0x%x\n", path_name, status);
- return status;
- }
- segnum = 0;
- }
-
- /* get bus number of this pci root bridge */
- status = acpi_evaluate_integer(handle, METHOD_NAME__BBN, NULL, &busnum);
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:%s evaluate _BBN fail=0x%x\n", path_name, status);
- return (status);
- }
-
- ab = add_host_bridge(handle, segnum, busnum);
- if (ab) {
- status = acpi_walk_namespace ( ACPI_TYPE_DEVICE,
- handle,
- 1,
- scan_p2p_bridge,
- ab,
- NULL);
- if (ACPI_FAILURE(status))
- dbg("acpi_pciehprm:%s find_p2p fail=0x%x\n", path_name, status);
+ break;
}
- return AE_OK;
+ err("Cannot get control of hotplug hardware for pci %s\n",
+ pci_name(dev));
+ return -1;
}
-static int pciehprm_acpi_scan_pci (void)
+void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
{
- acpi_status status;
+ acpi_status status = AE_NOT_FOUND;
+ struct pci_dev *pdev = dev;
/*
- * TBD: traverse LDM device tree with the help of
- * unified ACPI augmented for php device population.
+ * _HPP settings apply to all child buses, until another _HPP is
+ * encountered. If we don't find an _HPP for the input pci dev,
+ * look for it in the parent device scope since that would apply to
+ * this pci dev. If we don't find any _HPP, use hardcoded defaults
*/
- status = acpi_get_devices ( PCI_ROOT_HID_STRING,
- acpi_scan_from_root_pci_callback,
- NULL,
- NULL );
- if (ACPI_FAILURE(status)) {
- err("acpi_pciehprm:get_device PCI ROOT HID fail=0x%x\n", status);
- return -1;
- }
-
- return 0;
-}
-
-int pciehprm_init(enum php_ctlr_type ctlr_type)
-{
- int rc;
-
- if (ctlr_type != PCI)
- return -ENODEV;
-
- dbg("pciehprm ACPI init <enter>\n");
- acpi_bridges_head = NULL;
-
- /* construct PCI bus:device tree of acpi_handles */
- rc = pciehprm_acpi_scan_pci();
- if (rc)
- return rc;
-
- if ((oshp_run_status != NC_RUN_SUCCESS) && (osc_run_status != NC_RUN_SUCCESS)) {
- err("Fails to gain control of native hot-plug\n");
- rc = -ENODEV;
- }
-
- dbg("pciehprm ACPI init %s\n", (rc)?"fail":"success");
- return rc;
-}
-
-static void free_a_slot(struct acpi_php_slot *aps)
-{
- dbg(" free a php func of slot(0x%02x) on PCI b:d:f=0x%02x:%02x:%02x\n", aps->sun, aps->bus, aps->dev, aps->fun);
-
- free_pci_resource (aps->io_head);
- free_pci_resource (aps->bus_head);
- free_pci_resource (aps->mem_head);
- free_pci_resource (aps->p_mem_head);
-
- kfree(aps);
-}
-
-static void free_a_bridge( struct acpi_bridge *ab)
-{
- struct acpi_php_slot *aps, *next;
-
- switch (ab->type) {
- case BRIDGE_TYPE_HOST:
- dbg("Free ACPI PCI HOST Bridge(%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
- ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
- break;
- case BRIDGE_TYPE_P2P:
- dbg("Free ACPI PCI P2P Bridge(%x-%x) [%s] on s:b:d:f(%x:%x:%x:%x)\n",
- ab->pbus, ab->bus, acpi_path_name(ab->handle), ab->seg, ab->pbus, ab->pdevice, ab->pfunction);
- break;
- };
-
- /* free slots first */
- for (aps = ab->slots; aps; aps = next) {
- next = aps->next;
- free_a_slot(aps);
- }
-
- free_pci_resource (ab->io_head);
- free_pci_resource (ab->tio_head);
- free_pci_resource (ab->bus_head);
- free_pci_resource (ab->tbus_head);
- free_pci_resource (ab->mem_head);
- free_pci_resource (ab->tmem_head);
- free_pci_resource (ab->p_mem_head);
- free_pci_resource (ab->tp_mem_head);
-
- kfree(ab);
-}
-
-static void pciehprm_free_bridges ( struct acpi_bridge *ab)
-{
- if (!ab)
- return;
-
- if (ab->child)
- pciehprm_free_bridges (ab->child);
-
- if (ab->next)
- pciehprm_free_bridges (ab->next);
-
- free_a_bridge(ab);
-}
-
-void pciehprm_cleanup(void)
-{
- pciehprm_free_bridges (acpi_bridges_head);
-}
-
-static int get_number_of_slots (
- struct acpi_bridge *ab,
- int selfonly
- )
-{
- struct acpi_php_slot *aps;
- int prev_slot = -1;
- int slot_num = 0;
-
- for ( aps = ab->slots; aps; aps = aps->next)
- if (aps->dev != prev_slot) {
- prev_slot = aps->dev;
- slot_num++;
- }
-
- if (ab->child)
- slot_num += get_number_of_slots (ab->child, 0);
-
- if (selfonly)
- return slot_num;
-
- if (ab->next)
- slot_num += get_number_of_slots (ab->next, 0);
-
- return slot_num;
-}
-
-static int print_acpi_resources (struct acpi_bridge *ab)
-{
- struct acpi_php_slot *aps;
- int i;
-
- switch (ab->type) {
- case BRIDGE_TYPE_HOST:
- dbg("PCI HOST Bridge (%x) [%s]\n", ab->bus, acpi_path_name(ab->handle));
- break;
- case BRIDGE_TYPE_P2P:
- dbg("PCI P2P Bridge (%x-%x) [%s]\n", ab->pbus, ab->bus, acpi_path_name(ab->handle));
- break;
- };
-
- print_pci_resources (ab);
-
- for ( i = -1, aps = ab->slots; aps; aps = aps->next) {
- if (aps->dev == i)
- continue;
- dbg(" Slot sun(%x) s:b:d:f(%02x:%02x:%02x:%02x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
- print_slot_resources(aps);
- i = aps->dev;
- }
-
- if (ab->child)
- print_acpi_resources (ab->child);
-
- if (ab->next)
- print_acpi_resources (ab->next);
-
- return 0;
-}
-
-int pciehprm_print_pirt(void)
-{
- dbg("PCIEHPRM ACPI Slots\n");
- if (acpi_bridges_head)
- print_acpi_resources (acpi_bridges_head);
-
- return 0;
-}
-
-static struct acpi_php_slot * get_acpi_slot (
- struct acpi_bridge *ab,
- u32 sun
- )
-{
- struct acpi_php_slot *aps = NULL;
-
- for ( aps = ab->slots; aps; aps = aps->next)
- if (aps->sun == sun)
- return aps;
-
- if (!aps && ab->child) {
- aps = (struct acpi_php_slot *)get_acpi_slot (ab->child, sun);
- if (aps)
- return aps;
- }
-
- if (!aps && ab->next) {
- aps = (struct acpi_php_slot *)get_acpi_slot (ab->next, sun);
- if (aps)
- return aps;
- }
-
- return aps;
-
-}
-
-#if 0
-void * pciehprm_get_slot(struct slot *slot)
-{
- struct acpi_bridge *ab = acpi_bridges_head;
- struct acpi_php_slot *aps = get_acpi_slot (ab, slot->number);
-
- aps->slot = slot;
-
- dbg("Got acpi slot sun(%x): s:b:d:f(%x:%x:%x:%x)\n", aps->sun, aps->seg, aps->bus, aps->dev, aps->fun);
-
- return (void *)aps;
-}
-#endif
-
-static void pciehprm_dump_func_res( struct pci_func *fun)
-{
- struct pci_func *func = fun;
-
- if (func->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (func->bus_head);
- }
- if (func->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (func->io_head);
- }
- if (func->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (func->mem_head);
- }
- if (func->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (func->p_mem_head);
- }
-}
-
-static void pciehprm_dump_ctrl_res( struct controller *ctlr)
-{
- struct controller *ctrl = ctlr;
-
- if (ctrl->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (ctrl->bus_head);
- }
- if (ctrl->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (ctrl->io_head);
- }
- if (ctrl->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (ctrl->mem_head);
- }
- if (ctrl->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (ctrl->p_mem_head);
- }
-}
-
-static int pciehprm_get_used_resources (
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int configure_existing_function(
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- int rc;
-
- /* see how much resources the func has used. */
- rc = pciehprm_get_used_resources (ctrl, func);
-
- if (!rc) {
- /* subtract the resources used by the func from ctrl resources */
- rc = pciehprm_delete_resources (&ctrl->bus_head, func->bus_head);
- rc |= pciehprm_delete_resources (&ctrl->io_head, func->io_head);
- rc |= pciehprm_delete_resources (&ctrl->mem_head, func->mem_head);
- rc |= pciehprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
- if (rc)
- warn("aCEF: cannot del used resources\n");
- } else
- err("aCEF: cannot get used resources\n");
-
- return rc;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
-{
- struct pci_func *func, new_func;
- int busn = ctrl->slot_bus;
- int devn, funn;
- u32 vid;
-
- for (devn = 0; devn < 32; devn++) {
- for (funn = 0; funn < 8; funn++) {
- /*
- if (devn == ctrl->device && funn == ctrl->function)
- continue;
- */
- /* find out if this entry is for an occupied slot */
- vid = 0xFFFFFFFF;
- pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
- if (vid != 0xFFFFFFFF) {
- dbg("%s: vid = %x\n", __FUNCTION__, vid);
- func = pciehp_slot_find(busn, devn, funn);
- if (!func) {
- memset(&new_func, 0, sizeof(struct pci_func));
- new_func.bus = busn;
- new_func.device = devn;
- new_func.function = funn;
- new_func.is_a_board = 1;
- configure_existing_function(ctrl, &new_func);
- pciehprm_dump_func_res(&new_func);
- } else {
- configure_existing_function(ctrl, func);
- pciehprm_dump_func_res(func);
- }
- dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
- }
- }
- }
-
- return 0;
-}
-
-static int bind_pci_resources(
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int status = 0;
-
- if (ab->bus_head) {
- dbg("bapr: BUS Resources add on PCI 0x%x\n", ab->bus);
- status = pciehprm_add_resources (&ctrl->bus_head, ab->bus_head);
- if (pciehprm_delete_resources (&ab->bus_head, ctrl->bus_head))
- warn("bapr: cannot sub BUS Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: BUS Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No BUS Resource on PCI 0x%x.\n", ab->bus);
-
- if (ab->io_head) {
- dbg("bapr: IO Resources add on PCI 0x%x\n", ab->bus);
- status = pciehprm_add_resources (&ctrl->io_head, ab->io_head);
- if (pciehprm_delete_resources (&ab->io_head, ctrl->io_head))
- warn("bapr: cannot sub IO Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: IO Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No IO Resource on PCI 0x%x.\n", ab->bus);
-
- if (ab->mem_head) {
- dbg("bapr: MEM Resources add on PCI 0x%x\n", ab->bus);
- status = pciehprm_add_resources (&ctrl->mem_head, ab->mem_head);
- if (pciehprm_delete_resources (&ab->mem_head, ctrl->mem_head))
- warn("bapr: cannot sub MEM Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: MEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No MEM Resource on PCI 0x%x.\n", ab->bus);
-
- if (ab->p_mem_head) {
- dbg("bapr: PMEM Resources add on PCI 0x%x\n", ab->bus);
- status = pciehprm_add_resources (&ctrl->p_mem_head, ab->p_mem_head);
- if (pciehprm_delete_resources (&ab->p_mem_head, ctrl->p_mem_head))
- warn("bapr: cannot sub PMEM Resource on PCI 0x%x\n", ab->bus);
- if (status) {
- err("bapr: PMEM Resource add on PCI 0x%x: fail=0x%x\n", ab->bus, status);
- return status;
- }
- } else
- info("bapr: No PMEM Resource on PCI 0x%x.\n", ab->bus);
-
- return status;
-}
-
-static int no_pci_resources( struct acpi_bridge *ab)
-{
- return !(ab->p_mem_head || ab->mem_head || ab->io_head || ab->bus_head);
-}
-
-static int find_pci_bridge_resources (
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int rc = 0;
- struct pci_func func;
-
- memset(&func, 0, sizeof(struct pci_func));
-
- func.bus = ab->pbus;
- func.device = ab->pdevice;
- func.function = ab->pfunction;
- func.is_a_board = 1;
-
- /* Get used resources for this PCI bridge */
- rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD);
-
- ab->io_head = func.io_head;
- ab->mem_head = func.mem_head;
- ab->p_mem_head = func.p_mem_head;
- ab->bus_head = func.bus_head;
- if (ab->bus_head)
- pciehprm_delete_resource(&ab->bus_head, ctrl->pci_dev->subordinate->number, 1);
-
- return rc;
-}
-
-static int get_pci_resources_from_bridge(
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int rc = 0;
-
- dbg("grfb: Get Resources for PCI 0x%x from actual PCI bridge 0x%x.\n", ctrl->bus, ab->bus);
-
- rc = find_pci_bridge_resources (ctrl, ab);
-
- pciehp_resource_sort_and_combine(&ab->bus_head);
- pciehp_resource_sort_and_combine(&ab->io_head);
- pciehp_resource_sort_and_combine(&ab->mem_head);
- pciehp_resource_sort_and_combine(&ab->p_mem_head);
-
- pciehprm_add_resources (&ab->tbus_head, ab->bus_head);
- pciehprm_add_resources (&ab->tio_head, ab->io_head);
- pciehprm_add_resources (&ab->tmem_head, ab->mem_head);
- pciehprm_add_resources (&ab->tp_mem_head, ab->p_mem_head);
-
- return rc;
-}
-
-static int get_pci_resources(
- struct controller *ctrl,
- struct acpi_bridge *ab
- )
-{
- int rc = 0;
-
- if (no_pci_resources(ab)) {
- dbg("spbr:PCI 0x%x has no resources. Get parent resources.\n", ab->bus);
- rc = get_pci_resources_from_bridge(ctrl, ab);
- }
-
- return rc;
-}
-
-/*
- * Get resources for this ctrl.
- * 1. get total resources from ACPI _CRS or bridge (this ctrl)
- * 2. find used resources of existing adapters
- * 3. subtract used resources from total resources
- */
-int pciehprm_find_available_resources( struct controller *ctrl)
-{
- int rc = 0;
- struct acpi_bridge *ab;
-
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->pci_dev->subordinate->number);
- if (!ab) {
- err("pfar:cannot locate acpi bridge of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
- return -1;
- }
- if (no_pci_resources(ab)) {
- rc = get_pci_resources(ctrl, ab);
- if (rc) {
- err("pfar:cannot get pci resources of PCI 0x%x.\n", ctrl->pci_dev->subordinate->number);
- return -1;
- }
- }
-
- rc = bind_pci_resources(ctrl, ab);
- dbg("pfar:pre-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
- pciehprm_dump_ctrl_res(ctrl);
-
- bind_pci_resources_to_slots (ctrl);
-
- dbg("pfar:post-Bind PCI 0x%x Ctrl Resource Dump\n", ctrl->pci_dev->subordinate->number);
- pciehprm_dump_ctrl_res(ctrl);
-
- return rc;
-}
-
-int pciehprm_set_hpp(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type
- )
-{
- struct acpi_bridge *ab;
- struct pci_bus lpci_bus, *pci_bus;
- int rc = 0;
- unsigned int devfn;
- u8 cls= 0x08; /* default cache line size */
- u8 lt = 0x40; /* default latency timer */
- u8 ep = 0;
- u8 es = 0;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
-
- if (ab) {
- if (ab->_hpp) {
- lt = (u8)ab->_hpp->latency_timer;
- cls = (u8)ab->_hpp->cache_line_size;
- ep = (u8)ab->_hpp->enable_perr;
- es = (u8)ab->_hpp->enable_serr;
- } else
- dbg("_hpp: no _hpp for B/D/F=%#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
- } else
- dbg("_hpp: no acpi bridge for B/D/F = %#x/%#x/%#x. use default value\n", func->bus, func->device, func->function);
-
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- /* set subordinate Latency Timer */
- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, lt);
+ while (pdev && (ACPI_FAILURE(status))) {
+ acpi_handle handle = DEVICE_ACPI_HANDLE(&(pdev->dev));
+ if (!handle)
+ break;
+ status = acpi_run_hpp(handle, hpp);
+ if (!(pdev->bus->parent))
+ break;
+ /* Check if a parent object supports _HPP */
+ pdev = pdev->bus->parent->self;
}
-
- /* set base Latency Timer */
- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, lt);
- dbg(" set latency timer =0x%02x: %x\n", lt, rc);
-
- rc |= pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, cls);
- dbg(" set cache_line_size=0x%02x: %x\n", cls, rc);
-
- return rc;
}
-void pciehprm_enable_card(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
-{
- u16 command, cmd, bcommand, bcmd;
- struct pci_bus lpci_bus, *pci_bus;
- struct acpi_bridge *ab;
- unsigned int devfn;
- int rc;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &cmd);
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcmd);
- }
-
- command = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
- bcommand = bcmd | PCI_BRIDGE_CTL_NO_ISA;
-
- ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
- if (ab) {
- if (ab->_hpp) {
- if (ab->_hpp->enable_perr) {
- command |= PCI_COMMAND_PARITY;
- bcommand |= PCI_BRIDGE_CTL_PARITY;
- } else {
- command &= ~PCI_COMMAND_PARITY;
- bcommand &= ~PCI_BRIDGE_CTL_PARITY;
- }
- if (ab->_hpp->enable_serr) {
- command |= PCI_COMMAND_SERR;
- bcommand |= PCI_BRIDGE_CTL_SERR;
- } else {
- command &= ~PCI_COMMAND_SERR;
- bcommand &= ~PCI_BRIDGE_CTL_SERR;
- }
- } else
- dbg("no _hpp for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
- } else
- dbg("no acpi bridge for B/D/F = %#x/%#x/%#x.\n", func->bus, func->device, func->function);
-
- if (command != cmd) {
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
- }
- if ((card_type == PCI_HEADER_TYPE_BRIDGE) && (bcommand != bcmd)) {
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
- }
-}
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c
index 76c727c74cc0..29180dfe8493 100644
--- a/drivers/pci/hotplug/pciehprm_nonacpi.c
+++ b/drivers/pci/hotplug/pciehprm_nonacpi.c
@@ -27,479 +27,21 @@
*
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/pci.h>
-#include <linux/init.h>
#include <linux/slab.h>
-
-#include <asm/uaccess.h>
-#ifdef CONFIG_IA64
-#include <asm/iosapic.h>
-#endif
-
#include "pciehp.h"
-#include "pciehprm.h"
-#include "pciehprm_nonacpi.h"
-
-void pciehprm_cleanup(void)
+void pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
+ struct hotplug_params *hpp)
{
return;
}
-int pciehprm_print_pirt(void)
-{
- return 0;
-}
-
-int pciehprm_get_physical_slot_number(struct controller *ctrl, u32 *sun, u8 busnum, u8 devnum)
-{
-
- *sun = (u8) (ctrl->first_slot);
- return 0;
-}
-
-
-static void print_pci_resource ( struct pci_resource *aprh)
-{
- struct pci_resource *res;
-
- for (res = aprh; res; res = res->next)
- dbg(" base= 0x%x length= 0x%x\n", res->base, res->length);
-}
-
-
-static void phprm_dump_func_res( struct pci_func *fun)
-{
- struct pci_func *func = fun;
-
- if (func->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (func->bus_head);
- }
- if (func->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (func->io_head);
- }
- if (func->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (func->mem_head);
- }
- if (func->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (func->p_mem_head);
- }
-}
-
-static int phprm_get_used_resources (
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- return pciehp_save_used_resources (ctrl, func, !DISABLE_CARD);
-}
-
-static int phprm_delete_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
- struct pci_resource *prevnode;
- struct pci_resource *split_node;
- ulong tbase;
-
- pciehp_resource_sort_and_combine(aprh);
-
- for (res = *aprh; res; res = res->next) {
- if (res->base > base)
- continue;
-
- if ((res->base + res->length) < (base + size))
- continue;
-
- if (res->base < base) {
- tbase = base;
-
- if ((res->length - (tbase - res->base)) < size)
- continue;
-
- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base;
- split_node->length = tbase - res->base;
- res->base = tbase;
- res->length -= split_node->length;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (res->length >= size) {
- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base + size;
- split_node->length = res->length - size;
- res->length = size;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (*aprh == res) {
- *aprh = res->next;
- } else {
- prevnode = *aprh;
- while (prevnode->next != res)
- prevnode = prevnode->next;
-
- prevnode->next = res->next;
- }
- res->next = NULL;
- kfree(res);
- break;
- }
-
- return 0;
-}
-
-
-static int phprm_delete_resources(
- struct pci_resource **aprh,
- struct pci_resource *this
- )
-{
- struct pci_resource *res;
-
- for (res = this; res; res = res->next)
- phprm_delete_resource(aprh, res->base, res->length);
-
- return 0;
-}
-
-
-static int configure_existing_function(
- struct controller *ctrl,
- struct pci_func *func
- )
-{
- int rc;
-
- /* see how much resources the func has used. */
- rc = phprm_get_used_resources (ctrl, func);
-
- if (!rc) {
- /* subtract the resources used by the func from ctrl resources */
- rc = phprm_delete_resources (&ctrl->bus_head, func->bus_head);
- rc |= phprm_delete_resources (&ctrl->io_head, func->io_head);
- rc |= phprm_delete_resources (&ctrl->mem_head, func->mem_head);
- rc |= phprm_delete_resources (&ctrl->p_mem_head, func->p_mem_head);
- if (rc)
- warn("aCEF: cannot del used resources\n");
- } else
- err("aCEF: cannot get used resources\n");
-
- return rc;
-}
-
-static int pciehprm_delete_resource(
- struct pci_resource **aprh,
- ulong base,
- ulong size)
-{
- struct pci_resource *res;
- struct pci_resource *prevnode;
- struct pci_resource *split_node;
- ulong tbase;
-
- pciehp_resource_sort_and_combine(aprh);
-
- for (res = *aprh; res; res = res->next) {
- if (res->base > base)
- continue;
-
- if ((res->base + res->length) < (base + size))
- continue;
-
- if (res->base < base) {
- tbase = base;
-
- if ((res->length - (tbase - res->base)) < size)
- continue;
-
- split_node = (struct pci_resource *) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base;
- split_node->length = tbase - res->base;
- res->base = tbase;
- res->length -= split_node->length;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (res->length >= size) {
- split_node = (struct pci_resource*) kmalloc(sizeof(struct pci_resource), GFP_KERNEL);
- if (!split_node)
- return -ENOMEM;
-
- split_node->base = res->base + size;
- split_node->length = res->length - size;
- res->length = size;
-
- split_node->next = res->next;
- res->next = split_node;
- }
-
- if (*aprh == res) {
- *aprh = res->next;
- } else {
- prevnode = *aprh;
- while (prevnode->next != res)
- prevnode = prevnode->next;
-
- prevnode->next = res->next;
- }
- res->next = NULL;
- kfree(res);
- break;
- }
-
- return 0;
-}
-
-static int bind_pci_resources_to_slots ( struct controller *ctrl)
+int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
- struct pci_func *func, new_func;
- int busn = ctrl->slot_bus;
- int devn, funn;
- u32 vid;
-
- for (devn = 0; devn < 32; devn++) {
- for (funn = 0; funn < 8; funn++) {
- /*
- if (devn == ctrl->device && funn == ctrl->function)
- continue;
- */
- /* find out if this entry is for an occupied slot */
- vid = 0xFFFFFFFF;
-
- pci_bus_read_config_dword(ctrl->pci_dev->subordinate, PCI_DEVFN(devn, funn), PCI_VENDOR_ID, &vid);
-
- if (vid != 0xFFFFFFFF) {
- dbg("%s: vid = %x bus %x dev %x fun %x\n", __FUNCTION__,
- vid, busn, devn, funn);
- func = pciehp_slot_find(busn, devn, funn);
- dbg("%s: func = %p\n", __FUNCTION__,func);
- if (!func) {
- memset(&new_func, 0, sizeof(struct pci_func));
- new_func.bus = busn;
- new_func.device = devn;
- new_func.function = funn;
- new_func.is_a_board = 1;
- configure_existing_function(ctrl, &new_func);
- phprm_dump_func_res(&new_func);
- } else {
- configure_existing_function(ctrl, func);
- phprm_dump_func_res(func);
- }
- dbg("aCCF:existing PCI 0x%x Func ResourceDump\n", ctrl->bus);
- }
- }
- }
-
return 0;
}
-
-static void phprm_dump_ctrl_res( struct controller *ctlr)
-{
- struct controller *ctrl = ctlr;
-
- if (ctrl->bus_head) {
- dbg(": BUS Resources:\n");
- print_pci_resource (ctrl->bus_head);
- }
- if (ctrl->io_head) {
- dbg(": IO Resources:\n");
- print_pci_resource (ctrl->io_head);
- }
- if (ctrl->mem_head) {
- dbg(": MEM Resources:\n");
- print_pci_resource (ctrl->mem_head);
- }
- if (ctrl->p_mem_head) {
- dbg(": PMEM Resources:\n");
- print_pci_resource (ctrl->p_mem_head);
- }
-}
-
-/*
- * phprm_find_available_resources
- *
- * Finds available memory, IO, and IRQ resources for programming
- * devices which may be added to the system
- * this function is for hot plug ADD!
- *
- * returns 0 if success
- */
-int pciehprm_find_available_resources(struct controller *ctrl)
-{
- struct pci_func func;
- u32 rc;
-
- memset(&func, 0, sizeof(struct pci_func));
-
- func.bus = ctrl->bus;
- func.device = ctrl->device;
- func.function = ctrl->function;
- func.is_a_board = 1;
-
- /* Get resources for this PCI bridge */
- rc = pciehp_save_used_resources (ctrl, &func, !DISABLE_CARD);
- dbg("%s: pciehp_save_used_resources rc = %d\n", __FUNCTION__, rc);
-
- if (func.mem_head)
- func.mem_head->next = ctrl->mem_head;
- ctrl->mem_head = func.mem_head;
-
- if (func.p_mem_head)
- func.p_mem_head->next = ctrl->p_mem_head;
- ctrl->p_mem_head = func.p_mem_head;
-
- if (func.io_head)
- func.io_head->next = ctrl->io_head;
- ctrl->io_head = func.io_head;
-
- if(func.bus_head)
- func.bus_head->next = ctrl->bus_head;
- ctrl->bus_head = func.bus_head;
-
- if (ctrl->bus_head)
- pciehprm_delete_resource(&ctrl->bus_head, ctrl->pci_dev->subordinate->number, 1);
-
- dbg("%s:pre-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
- phprm_dump_ctrl_res(ctrl);
-
- dbg("%s: before bind_pci_resources_to slots\n", __FUNCTION__);
-
- bind_pci_resources_to_slots (ctrl);
-
- dbg("%s:post-Bind PCI 0x%x Ctrl Resource Dump\n", __FUNCTION__, ctrl->bus);
- phprm_dump_ctrl_res(ctrl);
-
- return (rc);
-}
-
-int pciehprm_set_hpp(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
-{
- u32 rc;
- u8 temp_byte;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- temp_byte = 0x40; /* hard coded value for LT */
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
- /* set subordinate Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_SEC_LATENCY_TIMER, temp_byte);
-
- if (rc) {
- dbg("%s: set secondary LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__,
- func->bus, func->device, func->function);
- return rc;
- }
- }
-
- /* set base Latency Timer */
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_LATENCY_TIMER, temp_byte);
-
- if (rc) {
- dbg("%s: set LT error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- return rc;
- }
-
- /* set Cache Line size */
- temp_byte = 0x08; /* hard coded value for CLS */
-
- rc = pci_bus_write_config_byte(pci_bus, devfn, PCI_CACHE_LINE_SIZE, temp_byte);
-
- if (rc) {
- dbg("%s: set CLS error. b:d:f(%02x:%02x:%02x)\n", __FUNCTION__, func->bus, func->device, func->function);
- }
-
- /* set enable_perr */
- /* set enable_serr */
-
- return rc;
-}
-
-void pciehprm_enable_card(
- struct controller *ctrl,
- struct pci_func *func,
- u8 card_type)
-{
- u16 command, bcommand;
- struct pci_bus lpci_bus, *pci_bus;
- unsigned int devfn;
- int rc;
-
- memcpy(&lpci_bus, ctrl->pci_bus, sizeof(lpci_bus));
- pci_bus = &lpci_bus;
- pci_bus->number = func->bus;
- devfn = PCI_DEVFN(func->device, func->function);
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_COMMAND, &command);
-
- command |= PCI_COMMAND_PARITY | PCI_COMMAND_SERR
- | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE
- | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
-
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_COMMAND, command);
-
- if (card_type == PCI_HEADER_TYPE_BRIDGE) {
-
- rc = pci_bus_read_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, &bcommand);
-
- bcommand |= PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR
- | PCI_BRIDGE_CTL_NO_ISA;
-
- rc = pci_bus_write_config_word(pci_bus, devfn, PCI_BRIDGE_CONTROL, bcommand);
- }
-}
-
-static int legacy_pciehprm_init_pci(void)
-{
- return 0;
-}
-
-int pciehprm_init(enum php_ctlr_type ctrl_type)
-{
- int retval;
-
- switch (ctrl_type) {
- case PCI:
- retval = legacy_pciehprm_init_pci();
- break;
- default:
- retval = -ENODEV;
- break;
- }
-
- return retval;
-}
diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.h b/drivers/pci/hotplug/pciehprm_nonacpi.h
deleted file mode 100644
index b10603b0e958..000000000000
--- a/drivers/pci/hotplug/pciehprm_nonacpi.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * PCIEHPRM NONACPI: PHP Resource Manager for Non-ACPI/Legacy platform
- *
- * Copyright (C) 1995,2001 Compaq Computer Corporation
- * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
- * Copyright (C) 2001 IBM Corp.
- * Copyright (C) 2003-2004 Intel Corporation
- *
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- * NON INFRINGEMENT. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
- *
- */
-
-#ifndef _PCIEHPRM_NONACPI_H_
-#define _PCIEHPRM_NONACPI_H_
-
-struct irq_info {
- u8 bus, devfn; /* bus, device and function */
- struct {
- u8 link; /* IRQ line ID, chipset dependent, 0=not routed */
- u16 bitmap; /* Available IRQs */
- } __attribute__ ((packed)) irq[4];
- u8 slot; /* slot number, 0=onboard */
- u8 rfu;
-} __attribute__ ((packed));
-
-struct irq_routing_table {
- u32 signature; /* PIRQ_SIGNATURE should be here */
- u16 version; /* PIRQ_VERSION */
- u16 size; /* Table size in bytes */
- u8 rtr_bus, rtr_devfn; /* Where the interrupt router lies */
- u16 exclusive_irqs; /* IRQs devoted exclusively to PCI usage */
- u16 rtr_vendor, rtr_device; /* Vendor and device ID of interrupt router */
- u32 miniport_data; /* Crap */
- u8 rfu[11];
- u8 checksum; /* Modulo 256 checksum must give zero */
- struct irq_info slots[0];
-} __attribute__ ((packed));
-
-#endif /* _PCIEHPRM_NONACPI_H_ */
diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
index fcb66b9a0e28..cc03609f45d0 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -134,43 +134,6 @@ static void rpadlpar_claim_one_bus(struct pci_bus *b)
rpadlpar_claim_one_bus(child_bus);
}
-static int pci_add_secondary_bus(struct device_node *dn,
- struct pci_dev *bridge_dev)
-{
- struct pci_dn *pdn = dn->data;
- struct pci_controller *hose = pdn->phb;
- struct pci_bus *child;
- u8 sec_busno;
-
- /* Get busno of downstream bus */
- pci_read_config_byte(bridge_dev, PCI_SECONDARY_BUS, &sec_busno);
-
- /* Allocate and add to children of bridge_dev->bus */
- child = pci_add_new_bus(bridge_dev->bus, bridge_dev, sec_busno);
- if (!child) {
- printk(KERN_ERR "%s: could not add secondary bus\n", __FUNCTION__);
- return -ENOMEM;
- }
-
- sprintf(child->name, "PCI Bus #%02x", child->number);
-
- /* Fixup subordinate bridge bases and resources */
- pcibios_fixup_bus(child);
-
- /* Claim new bus resources */
- rpadlpar_claim_one_bus(bridge_dev->bus);
-
- if (hose->last_busno < child->number)
- hose->last_busno = child->number;
-
- pdn->bussubno = child->number;
-
- /* ioremap() for child bus, which may or may not succeed */
- remap_bus_range(child);
-
- return 0;
-}
-
static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
struct device_node *dev_dn)
{
@@ -188,29 +151,41 @@ static struct pci_dev *dlpar_find_new_dev(struct pci_bus *parent,
static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
{
struct pci_dn *pdn = dn->data;
- struct pci_controller *hose = pdn->phb;
+ struct pci_controller *phb = pdn->phb;
struct pci_dev *dev = NULL;
- /* Scan phb bus for EADS device, adding new one to bus->devices */
- if (!pci_scan_single_device(hose->bus, pdn->devfn)) {
- printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__);
+ rpaphp_eeh_init_nodes(dn);
+ /* Add EADS device to PHB bus, adding new entry to bus->devices */
+ dev = of_create_pci_dev(dn, phb->bus, pdn->devfn);
+ if (!dev) {
+ printk(KERN_ERR "%s: failed to create pci dev for %s\n",
+ __FUNCTION__, dn->full_name);
return NULL;
}
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
+ dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
+ of_scan_pci_bridge(dn, dev);
+
+ rpaphp_init_new_devs(dev->subordinate);
+
+ /* Claim new bus resources */
+ rpadlpar_claim_one_bus(dev->bus);
+
+ /* ioremap() for child bus, which may or may not succeed */
+ (void) remap_bus_range(dev->bus);
+
/* Add new devices to global lists. Register in proc, sysfs. */
- pci_bus_add_devices(hose->bus);
+ pci_bus_add_devices(phb->bus);
/* Confirm new bridge dev was created */
- dev = dlpar_find_new_dev(hose->bus, dn);
+ dev = dlpar_find_new_dev(phb->bus, dn);
if (dev) {
if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
printk(KERN_ERR "%s: unexpected header type %d\n",
__FUNCTION__, dev->hdr_type);
return NULL;
}
-
- if (pci_add_secondary_bus(dn, dev))
- return NULL;
}
return dev;
@@ -219,7 +194,6 @@ static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
{
struct pci_dev *dev;
- int rc;
if (rpaphp_find_pci_bus(dn))
return -EINVAL;
@@ -232,15 +206,6 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
return -EIO;
}
- if (dn->child) {
- rc = rpaphp_config_pci_adapter(dev->subordinate);
- if (rc < 0) {
- printk(KERN_ERR "%s: unable to enable slot %s\n",
- __FUNCTION__, drc_name);
- return -EIO;
- }
- }
-
/* Add hotplug slot */
if (rpaphp_add_slot(dn)) {
printk(KERN_ERR "%s: unable to add hotplug slot %s\n",
@@ -306,7 +271,7 @@ static int dlpar_add_phb(char *drc_name, struct device_node *dn)
{
struct pci_controller *phb;
- if (PCI_DN(dn)->phb) {
+ if (PCI_DN(dn) && PCI_DN(dn)->phb) {
/* PHB already exists */
return -EINVAL;
}
@@ -435,6 +400,8 @@ int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
__FUNCTION__, drc_name);
return -EIO;
}
+ } else {
+ rpaphp_unconfig_pci_adapter(bus);
}
if (unmap_bus_range(bus)) {
diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
index 71ea5f9bb284..57ea71a7bda5 100644
--- a/drivers/pci/hotplug/rpaphp.h
+++ b/drivers/pci/hotplug/rpaphp.h
@@ -93,6 +93,8 @@ extern int rpaphp_claim_resource(struct pci_dev *dev, int resource);
extern int rpaphp_enable_pci_slot(struct slot *slot);
extern int register_pci_slot(struct slot *slot);
extern int rpaphp_get_pci_adapter_status(struct slot *slot, int is_init, u8 * value);
+extern void rpaphp_init_new_devs(struct pci_bus *bus);
+extern void rpaphp_eeh_init_nodes(struct device_node *dn);
extern int rpaphp_config_pci_adapter(struct pci_bus *bus);
extern int rpaphp_unconfig_pci_adapter(struct pci_bus *bus);
diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
index f7c12d7dfcfc..a7859a84d1ae 100644
--- a/drivers/pci/hotplug/rpaphp_pci.c
+++ b/drivers/pci/hotplug/rpaphp_pci.c
@@ -154,8 +154,7 @@ exit:
}
/* Must be called before pci_bus_add_devices */
-static void
-rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
+void rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
{
struct pci_dev *dev;
@@ -184,6 +183,20 @@ rpaphp_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus)
}
}
+static void rpaphp_eeh_add_bus_device(struct pci_bus *bus)
+{
+ struct pci_dev *dev;
+
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ eeh_add_device_late(dev);
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+ struct pci_bus *subbus = dev->subordinate;
+ if (subbus)
+ rpaphp_eeh_add_bus_device (subbus);
+ }
+ }
+}
+
static int rpaphp_pci_config_bridge(struct pci_dev *dev)
{
u8 sec_busno;
@@ -217,6 +230,13 @@ static int rpaphp_pci_config_bridge(struct pci_dev *dev)
return 0;
}
+void rpaphp_init_new_devs(struct pci_bus *bus)
+{
+ rpaphp_fixup_new_pci_devices(bus, 0);
+ rpaphp_eeh_add_bus_device(bus);
+}
+EXPORT_SYMBOL_GPL(rpaphp_init_new_devs);
+
/*****************************************************************************
rpaphp_pci_config_slot() will configure all devices under the
given slot->dn and return the the first pci_dev.
@@ -233,36 +253,51 @@ rpaphp_pci_config_slot(struct pci_bus *bus)
if (!dn || !dn->child)
return NULL;
- slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
+ if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
+ of_scan_bus(dn, bus);
+ if (list_empty(&bus->devices)) {
+ err("%s: No new device found\n", __FUNCTION__);
+ return NULL;
+ }
- /* pci_scan_slot should find all children */
- num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
- if (num) {
- rpaphp_fixup_new_pci_devices(bus, 1);
+ rpaphp_init_new_devs(bus);
pci_bus_add_devices(bus);
- }
- if (list_empty(&bus->devices)) {
- err("%s: No new device found\n", __FUNCTION__);
- return NULL;
- }
- list_for_each_entry(dev, &bus->devices, bus_list) {
- if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
- rpaphp_pci_config_bridge(dev);
+ dev = list_entry(&bus->devices, struct pci_dev, bus_list);
+ } else {
+ slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
+
+ /* pci_scan_slot should find all children */
+ num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
+ if (num) {
+ rpaphp_fixup_new_pci_devices(bus, 1);
+ pci_bus_add_devices(bus);
+ }
+ if (list_empty(&bus->devices)) {
+ err("%s: No new device found\n", __FUNCTION__);
+ return NULL;
+ }
+ list_for_each_entry(dev, &bus->devices, bus_list) {
+ if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+ rpaphp_pci_config_bridge(dev);
+
+ rpaphp_eeh_add_bus_device(bus);
+ }
}
return dev;
}
-static void enable_eeh(struct device_node *dn)
+void rpaphp_eeh_init_nodes(struct device_node *dn)
{
struct device_node *sib;
for (sib = dn->child; sib; sib = sib->sibling)
- enable_eeh(sib);
+ rpaphp_eeh_init_nodes(sib);
eeh_add_device_early(dn);
return;
}
+EXPORT_SYMBOL_GPL(rpaphp_eeh_init_nodes);
static void print_slot_pci_funcs(struct pci_bus *bus)
{
@@ -289,7 +324,7 @@ int rpaphp_config_pci_adapter(struct pci_bus *bus)
if (!dn)
goto exit;
- enable_eeh(dn);
+ rpaphp_eeh_init_nodes(dn);
dev = rpaphp_pci_config_slot(bus);
if (!dev) {
err("%s: can't find any devices.\n", __FUNCTION__);
@@ -331,6 +366,7 @@ int rpaphp_unconfig_pci_adapter(struct pci_bus *bus)
}
return 0;
}
+EXPORT_SYMBOL_GPL(rpaphp_unconfig_pci_adapter);
static int setup_pci_hotplug_slot_info(struct slot *slot)
{
@@ -444,8 +480,8 @@ int rpaphp_enable_pci_slot(struct slot *slot)
retval = rpaphp_config_pci_adapter(slot->bus);
if (!retval) {
slot->state = CONFIGURED;
- dbg("%s: PCI devices in slot[%s] has been configured\n",
- __FUNCTION__, slot->name);
+ info("%s: devices in slot[%s] configured\n",
+ __FUNCTION__, slot->name);
} else {
slot->state = NOT_CONFIGURED;
dbg("%s: no pci_dev struct for adapter in slot[%s]\n",
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c
index b8e95acea3b6..38009bc0fd5d 100644
--- a/drivers/pci/hotplug/shpchp_pci.c
+++ b/drivers/pci/hotplug/shpchp_pci.c
@@ -34,7 +34,7 @@
#include "../pci.h"
#include "shpchp.h"
-void program_fw_provided_values(struct pci_dev *dev)
+static void program_fw_provided_values(struct pci_dev *dev)
{
u16 pci_cmd, pci_bctl;
struct pci_dev *cdev;
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index a2033552423c..202b7507a357 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -23,6 +23,8 @@
#include "pci.h"
#include "msi.h"
+#define MSI_TARGET_CPU first_cpu(cpu_online_map)
+
static DEFINE_SPINLOCK(msi_lock);
static struct msi_desc* msi_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = NULL };
static kmem_cache_t* msi_cachep;
@@ -92,6 +94,7 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
struct msi_desc *entry;
struct msg_address address;
unsigned int irq = vector;
+ unsigned int dest_cpu = first_cpu(cpu_mask);
entry = (struct msi_desc *)msi_desc[vector];
if (!entry || !entry->dev)
@@ -108,9 +111,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
pci_read_config_dword(entry->dev, msi_lower_address_reg(pos),
&address.lo_address.value);
address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
- address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) <<
- MSI_TARGET_CPU_SHIFT);
- entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
+ address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
+ MSI_TARGET_CPU_SHIFT);
+ entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
pci_write_config_dword(entry->dev, msi_lower_address_reg(pos),
address.lo_address.value);
set_native_irq_info(irq, cpu_mask);
@@ -123,9 +126,9 @@ static void set_msi_affinity(unsigned int vector, cpumask_t cpu_mask)
address.lo_address.value = readl(entry->mask_base + offset);
address.lo_address.value &= MSI_ADDRESS_DEST_ID_MASK;
- address.lo_address.value |= (cpu_mask_to_apicid(cpu_mask) <<
- MSI_TARGET_CPU_SHIFT);
- entry->msi_attrib.current_cpu = cpu_mask_to_apicid(cpu_mask);
+ address.lo_address.value |= (cpu_physical_id(dest_cpu) <<
+ MSI_TARGET_CPU_SHIFT);
+ entry->msi_attrib.current_cpu = cpu_physical_id(dest_cpu);
writel(address.lo_address.value, entry->mask_base + offset);
set_native_irq_info(irq, cpu_mask);
break;
@@ -259,14 +262,15 @@ static void msi_data_init(struct msg_data *msi_data,
static void msi_address_init(struct msg_address *msi_address)
{
unsigned int dest_id;
+ unsigned long dest_phys_id = cpu_physical_id(MSI_TARGET_CPU);
memset(msi_address, 0, sizeof(struct msg_address));
msi_address->hi_address = (u32)0;
dest_id = (MSI_ADDRESS_HEADER << MSI_ADDRESS_HEADER_SHIFT);
- msi_address->lo_address.u.dest_mode = MSI_DEST_MODE;
+ msi_address->lo_address.u.dest_mode = MSI_PHYSICAL_MODE;
msi_address->lo_address.u.redirection_hint = MSI_REDIRECTION_HINT_MODE;
msi_address->lo_address.u.dest_id = dest_id;
- msi_address->lo_address.value |= (MSI_TARGET_CPU << MSI_TARGET_CPU_SHIFT);
+ msi_address->lo_address.value |= (dest_phys_id << MSI_TARGET_CPU_SHIFT);
}
static int msi_free_vector(struct pci_dev* dev, int vector, int reassign);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index e9e37abe1f76..a9b00cc2d885 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -91,9 +91,7 @@ acpi_query_osc (
static acpi_status
acpi_run_osc (
acpi_handle handle,
- u32 level,
- void *context,
- void **retval )
+ void *context)
{
acpi_status status;
struct acpi_object_list input;
@@ -184,7 +182,7 @@ EXPORT_SYMBOL(pci_osc_support_set);
*
* Attempt to take control from Firmware on requested control bits.
**/
-acpi_status pci_osc_control_set(u32 flags)
+acpi_status pci_osc_control_set(acpi_handle handle, u32 flags)
{
acpi_status status;
u32 ctrlset;
@@ -198,10 +196,7 @@ acpi_status pci_osc_control_set(u32 flags)
return AE_SUPPORT;
}
ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset;
- status = acpi_get_devices ( PCI_ROOT_HID_STRING,
- acpi_run_osc,
- ctrlset_buf,
- NULL );
+ status = acpi_run_osc(handle, ctrlset_buf);
if (ACPI_FAILURE (status)) {
ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset;
}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 94e68c54d273..a9046d4b8af3 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -37,7 +37,7 @@ struct pci_dynid {
* Adds a new dynamic pci device ID to this driver,
* and causes the driver to probe for all devices again.
*/
-static inline ssize_t
+static ssize_t
store_new_id(struct device_driver *driver, const char *buf, size_t count)
{
struct pci_dynid *dynid;
@@ -364,15 +364,16 @@ static struct kobj_type pci_driver_kobj_type = {
};
/**
- * pci_register_driver - register a new pci driver
+ * __pci_register_driver - register a new pci driver
* @drv: the driver structure to register
+ * @owner: owner module of drv
*
* Adds the driver structure to the list of registered drivers.
* Returns a negative value on error, otherwise 0.
* If no error occurred, the driver remains registered even if
* no device was claimed during registration.
*/
-int pci_register_driver(struct pci_driver *drv)
+int __pci_register_driver(struct pci_driver *drv, struct module *owner)
{
int error;
@@ -389,7 +390,7 @@ int pci_register_driver(struct pci_driver *drv)
printk(KERN_WARNING "Warning: PCI driver %s has a struct "
"device_driver shutdown method, please update!\n",
drv->name);
- drv->driver.owner = drv->owner;
+ drv->driver.owner = owner;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
spin_lock_init(&drv->dynids.lock);
@@ -526,7 +527,7 @@ postcore_initcall(pci_driver_init);
EXPORT_SYMBOL(pci_match_id);
EXPORT_SYMBOL(pci_match_device);
-EXPORT_SYMBOL(pci_register_driver);
+EXPORT_SYMBOL(__pci_register_driver);
EXPORT_SYMBOL(pci_unregister_driver);
EXPORT_SYMBOL(pci_dev_driver);
EXPORT_SYMBOL(pci_bus_type);
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index e74d75843047..8e287a828d5d 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -63,11 +63,38 @@ pci_max_busnr(void)
return max;
}
+static int __pci_find_next_cap(struct pci_bus *bus, unsigned int devfn, u8 pos, int cap)
+{
+ u8 id;
+ int ttl = 48;
+
+ while (ttl--) {
+ pci_bus_read_config_byte(bus, devfn, pos, &pos);
+ if (pos < 0x40)
+ break;
+ pos &= ~3;
+ pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID,
+ &id);
+ if (id == 0xff)
+ break;
+ if (id == cap)
+ return pos;
+ pos += PCI_CAP_LIST_NEXT;
+ }
+ return 0;
+}
+
+int pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap)
+{
+ return __pci_find_next_cap(dev->bus, dev->devfn,
+ pos + PCI_CAP_LIST_NEXT, cap);
+}
+EXPORT_SYMBOL_GPL(pci_find_next_capability);
+
static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_type, int cap)
{
u16 status;
- u8 pos, id;
- int ttl = 48;
+ u8 pos;
pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
if (!(status & PCI_STATUS_CAP_LIST))
@@ -76,24 +103,15 @@ static int __pci_bus_find_cap(struct pci_bus *bus, unsigned int devfn, u8 hdr_ty
switch (hdr_type) {
case PCI_HEADER_TYPE_NORMAL:
case PCI_HEADER_TYPE_BRIDGE:
- pci_bus_read_config_byte(bus, devfn, PCI_CAPABILITY_LIST, &pos);
+ pos = PCI_CAPABILITY_LIST;
break;
case PCI_HEADER_TYPE_CARDBUS:
- pci_bus_read_config_byte(bus, devfn, PCI_CB_CAPABILITY_LIST, &pos);
+ pos = PCI_CB_CAPABILITY_LIST;
break;
default:
return 0;
}
- while (ttl-- && pos >= 0x40) {
- pos &= ~3;
- pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_ID, &id);
- if (id == 0xff)
- break;
- if (id == cap)
- return pos;
- pci_bus_read_config_byte(bus, devfn, pos + PCI_CAP_LIST_NEXT, &pos);
- }
- return 0;
+ return __pci_find_next_cap(bus, devfn, pos, cap);
}
/**
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index 5627ce1d2b32..3a4f49f4effb 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -462,11 +462,11 @@ static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
pci_read_config_word(dev, 0x70, &hm);
hm &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c868 HW-mon");
+ quirk_io_region(dev, hm, 128, PCI_BRIDGE_RESOURCES + 1, "vt82c686 HW-mon");
pci_read_config_dword(dev, 0x90, &smb);
smb &= PCI_BASE_ADDRESS_IO_MASK;
- quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c868 SMB");
+ quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2, "vt82c686 SMB");
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_vt82c686_acpi );
@@ -1243,6 +1243,21 @@ static void __devinit quirk_netmos(struct pci_dev *dev)
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NETMOS, PCI_ANY_ID, quirk_netmos);
+
+static void __devinit fixup_rev1_53c810(struct pci_dev* dev)
+{
+ /* rev 1 ncr53c810 chips don't set the class at all which means
+ * they don't get their resources remapped. Fix that here.
+ */
+
+ if (dev->class == PCI_CLASS_NOT_DEFINED) {
+ printk(KERN_INFO "NCR 53c810 rev 1 detected, setting PCI class.\n");
+ dev->class = PCI_CLASS_STORAGE_SCSI;
+ }
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810);
+
+
static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end)
{
while (f < end) {
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
index ccf20039e909..309eb557f9a3 100644
--- a/drivers/pcmcia/Kconfig
+++ b/drivers/pcmcia/Kconfig
@@ -156,7 +156,7 @@ config TCIC
config PCMCIA_M8XX
tristate "MPC8xx PCMCIA support"
- depends on PCMCIA && PPC
+ depends on PCMCIA && PPC && 8xx
select PCCARD_NONSTATIC
help
Say Y here to include support for PowerPC 8xx series PCMCIA
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
index fe37541abbfe..bcecf5133b7e 100644
--- a/drivers/pcmcia/Makefile
+++ b/drivers/pcmcia/Makefile
@@ -25,7 +25,7 @@ obj-$(CONFIG_PD6729) += pd6729.o
obj-$(CONFIG_I82365) += i82365.o
obj-$(CONFIG_I82092) += i82092.o
obj-$(CONFIG_TCIC) += tcic.o
-obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
+obj-$(CONFIG_PCMCIA_M8XX) += m8xx_pcmcia.o
obj-$(CONFIG_HD64465_PCMCIA) += hd64465_ss.o
obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o
@@ -47,10 +47,10 @@ au1x00_ss-$(CONFIG_MIPS_PB1200) += au1000_db1x00.o
au1x00_ss-$(CONFIG_MIPS_PB1500) += au1000_pb1x00.o
au1x00_ss-$(CONFIG_MIPS_DB1000) += au1000_db1x00.o
au1x00_ss-$(CONFIG_MIPS_DB1100) += au1000_db1x00.o
-au1x00_ss-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o
+au1x00_ss-$(CONFIG_MIPS_DB1200) += au1000_db1x00.o
au1x00_ss-$(CONFIG_MIPS_DB1500) += au1000_db1x00.o
au1x00_ss-$(CONFIG_MIPS_DB1550) += au1000_db1x00.o
-au1x00_ss-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o
+au1x00_ss-$(CONFIG_MIPS_XXS1500) += au1000_xxs1500.o
sa1111_cs-y += sa1111_generic.o
sa1111_cs-$(CONFIG_ASSABET_NEPONSET) += sa1100_neponset.o
diff --git a/drivers/pcmcia/au1000_db1x00.c b/drivers/pcmcia/au1000_db1x00.c
index 24cfee1a412c..abc13f28ba3f 100644
--- a/drivers/pcmcia/au1000_db1x00.c
+++ b/drivers/pcmcia/au1000_db1x00.c
@@ -30,6 +30,7 @@
*
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
diff --git a/drivers/pcmcia/au1000_generic.h b/drivers/pcmcia/au1000_generic.h
index b0e7908392a7..f2c970b5f4ff 100644
--- a/drivers/pcmcia/au1000_generic.h
+++ b/drivers/pcmcia/au1000_generic.h
@@ -22,6 +22,8 @@
#define __ASM_AU1000_PCMCIA_H
/* include the world */
+#include <linux/config.h>
+
#include <pcmcia/cs_types.h>
#include <pcmcia/cs.h>
#include <pcmcia/ss.h>
diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c
index 86c0808d6a05..fd5522ede867 100644
--- a/drivers/pcmcia/au1000_pb1x00.c
+++ b/drivers/pcmcia/au1000_pb1x00.c
@@ -21,6 +21,7 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c
index 01a895bc9a47..01874b0bb03b 100644
--- a/drivers/pcmcia/au1000_xxs1500.c
+++ b/drivers/pcmcia/au1000_xxs1500.c
@@ -27,7 +27,6 @@
*/
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/config.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index 7ce455d01cc9..4ddd76239b34 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1366,6 +1366,7 @@ static int __init init_i82365(void)
if (sockets == 0) {
printk("not found.\n");
platform_device_unregister(&i82365_device);
+ release_region(i365_base, 2);
driver_unregister(&i82365_driver);
return -ENODEV;
}
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index f8bed87cf2f1..6d9f71cfcb34 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -39,7 +39,6 @@
#include <asm/io.h>
#include <asm/bitops.h>
-#include <asm/segment.h>
#include <asm/system.h>
#include <linux/kernel.h>
@@ -50,6 +49,7 @@
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
#include <asm/mpc8xx.h>
#include <asm/8xx_immap.h>
@@ -546,29 +546,11 @@ static void m8xx_shutdown(void)
free_irq(pcmcia_schlvl, NULL);
}
-/* copied from tcic.c */
-
-static int m8xx_drv_suspend(struct device *dev, pm_message_t state, u32 level)
-{
- int ret = 0;
- if (level == SUSPEND_SAVE_STATE)
- ret = pcmcia_socket_dev_suspend(dev, state);
- return ret;
-}
-
-static int m8xx_drv_resume(struct device *dev, u32 level)
-{
- int ret = 0;
- if (level == RESUME_RESTORE_STATE)
- ret = pcmcia_socket_dev_resume(dev);
- return ret;
-}
-
static struct device_driver m8xx_driver = {
.name = "m8xx-pcmcia",
.bus = &platform_bus_type,
- .suspend = m8xx_drv_suspend,
- .resume = m8xx_drv_resume,
+ .suspend = pcmcia_socket_dev_suspend,
+ .resume = pcmcia_socket_dev_resume,
};
static struct platform_device m8xx_device = {
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 2c86a4b809cd..c3a51d1fae5d 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -119,7 +119,7 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
__u8 regs = readb(d7s_regs);
__u8 ireg = 0;
- int error = 0
+ int error = 0;
if (D7S_MINOR != iminor(file->f_dentry->d_inode))
return -ENODEV;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index c90723860a04..07498118359d 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -1704,7 +1704,6 @@ MODULE_DEVICE_TABLE(pci, lpfc_id_table);
static struct pci_driver lpfc_driver = {
.name = LPFC_DRIVER_NAME,
- .owner = THIS_MODULE,
.id_table = lpfc_id_table,
.probe = lpfc_pci_probe_one,
.remove = __devexit_p(lpfc_pci_remove_one),
diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c
index 654469778ab5..b0f3cd63e3b9 100644
--- a/drivers/usb/gadget/goku_udc.c
+++ b/drivers/usb/gadget/goku_udc.c
@@ -1970,7 +1970,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
static struct pci_driver goku_pci_driver = {
.name = (char *) driver_name,
.id_table = pci_ids,
- .owner = THIS_MODULE,
.probe = goku_probe,
.remove = goku_remove,
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index 0dc6bb00bf72..c32e1f7476da 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -2948,7 +2948,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
static struct pci_driver net2280_pci_driver = {
.name = (char *) driver_name,
.id_table = pci_ids,
- .owner = THIS_MODULE,
.probe = net2280_probe,
.remove = net2280_remove,
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 145008853966..dfd9bd0b1828 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -383,7 +383,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
static struct pci_driver ehci_pci_driver = {
.name = (char *) hcd_name,
.id_table = pci_ids,
- .owner = THIS_MODULE,
.probe = usb_hcd_pci_probe,
.remove = usb_hcd_pci_remove,
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 7ce1d9ef0289..a59e536441e1 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -218,7 +218,6 @@ MODULE_DEVICE_TABLE (pci, pci_ids);
static struct pci_driver ohci_pci_driver = {
.name = (char *) hcd_name,
.id_table = pci_ids,
- .owner = THIS_MODULE,
.probe = usb_hcd_pci_probe,
.remove = usb_hcd_pci_remove,
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 15e0a511069b..d33ce3982a5f 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -831,7 +831,6 @@ MODULE_DEVICE_TABLE(pci, uhci_pci_ids);
static struct pci_driver uhci_pci_driver = {
.name = (char *)hcd_name,
.id_table = uhci_pci_ids,
- .owner = THIS_MODULE,
.probe = usb_hcd_pci_probe,
.remove = usb_hcd_pci_remove,
diff --git a/drivers/video/backlight/corgi_bl.c b/drivers/video/backlight/corgi_bl.c
index 4867498f68e8..bd9a6996aee7 100644
--- a/drivers/video/backlight/corgi_bl.c
+++ b/drivers/video/backlight/corgi_bl.c
@@ -48,6 +48,12 @@ static void corgibl_send_intensity(int intensity)
corgibl_mach_set_intensity(intensity);
spin_unlock_irqrestore(&bl_lock, flags);
+
+ corgi_kick_batt = symbol_get(sharpsl_battery_kick);
+ if (corgi_kick_batt) {
+ corgi_kick_batt();
+ symbol_put(sharpsl_battery_kick);
+ }
}
static void corgibl_blank(int blank)