Skip to content

Commit

Permalink
[IA64] hotplug/ia64: SN Hotplug Driver - SN Hotplug Driver code
Browse files Browse the repository at this point in the history
This patch is the SGI hotplug driver and additional changes required for
the driver.  These modifications include changes to the SN io_init.c code
for memory management, the inclusion of new SAL calls to enable and disable
PCI slots, and a hotplug-style driver.

Signed-off-by: Prarit Bhargava <prarit@sgi.com>
Signed-off-by: Tony Luck <tony.luck@intel.com>
  • Loading branch information
Prarit Bhargava authored and Tony Luck committed Jul 6, 2005
1 parent 283c7f6 commit 6f354b0
Show file tree
Hide file tree
Showing 8 changed files with 754 additions and 50 deletions.
134 changes: 89 additions & 45 deletions arch/ia64/sn/kernel/io_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@

nasid_t master_nasid = INVALID_NASID; /* Partition Master */

static struct list_head sn_sysdata_list;

/* sysdata list struct */
struct sysdata_el {
struct list_head entry;
void *sysdata;
};

struct slab_info {
struct hubdev_info hubdev;
};
Expand Down Expand Up @@ -136,23 +144,6 @@ sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
return ret_stuff.v0;
}

/*
* sn_alloc_pci_sysdata() - This routine allocates a pci controller
* which is expected as the pci_dev and pci_bus sysdata by the Linux
* PCI infrastructure.
*/
static inline struct pci_controller *sn_alloc_pci_sysdata(void)
{
struct pci_controller *pci_sysdata;

pci_sysdata = kmalloc(sizeof(*pci_sysdata), GFP_KERNEL);
if (!pci_sysdata)
BUG();

memset(pci_sysdata, 0, sizeof(*pci_sysdata));
return pci_sysdata;
}

/*
* sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
* each node in the system.
Expand Down Expand Up @@ -220,6 +211,15 @@ static void sn_fixup_ionodes(void)

}

void sn_pci_unfixup_slot(struct pci_dev *dev)
{
struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev;

sn_irq_unfixup(dev);
pci_dev_put(host_pci_dev);
pci_dev_put(dev);
}

/*
* sn_pci_fixup_slot() - This routine sets up a slot's resources
* consistent with the Linux PCI abstraction layer. Resources acquired
Expand All @@ -238,6 +238,7 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
unsigned long size;
unsigned int bus_no, devfn;

pci_dev_get(dev); /* for the sysdata pointer */
dev->sysdata = kmalloc(sizeof(struct pcidev_info), GFP_KERNEL);
if (SN_PCIDEV_INFO(dev) <= 0)
BUG(); /* Cannot afford to run out of memory */
Expand Down Expand Up @@ -276,7 +277,8 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
dev->resource[idx].parent = &iomem_resource;
}

/* Using the PROMs values for the PCI host bus, get the Linux
/*
* Using the PROMs values for the PCI host bus, get the Linux
* PCI host_pci_dev struct and set up host bus linkages
*/

Expand Down Expand Up @@ -313,55 +315,57 @@ void sn_pci_fixup_slot(struct pci_dev *dev)
* sn_pci_controller_fixup() - This routine sets up a bus's resources
* consistent with the Linux PCI abstraction layer.
*/
static void sn_pci_controller_fixup(int segment, int busnum)
void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
{
int status = 0;
int nasid, cnode;
struct pci_bus *bus;
struct pci_controller *controller;
struct pcibus_bussoft *prom_bussoft_ptr;
struct hubdev_info *hubdev_info;
void *provider_soft;
struct sn_pcibus_provider *provider;

status =
sal_get_pcibus_info((u64) segment, (u64) busnum,
(u64) ia64_tpa(&prom_bussoft_ptr));
if (status > 0) {
return; /* bus # does not exist */
}

status = sal_get_pcibus_info((u64) segment, (u64) busnum,
(u64) ia64_tpa(&prom_bussoft_ptr));
if (status > 0)
return; /*bus # does not exist */
prom_bussoft_ptr = __va(prom_bussoft_ptr);
controller = sn_alloc_pci_sysdata();
/* controller non-zero is BUG'd in sn_alloc_pci_sysdata */

bus = pci_scan_bus(busnum, &pci_root_ops, controller);
controller = kcalloc(1,sizeof(struct pci_controller), GFP_KERNEL);
if (!controller)
BUG();

if (bus == NULL) {
return; /* error, or bus already scanned */
bus = pci_scan_bus(busnum, &pci_root_ops, controller);
if (bus == NULL)
return; /* error, or bus already scanned */
bus->sysdata = NULL;
}

if (bus->sysdata)
goto error_return; /* sysdata already alloc'd */

/*
* Per-provider fixup. Copies the contents from prom to local
* area and links SN_PCIBUS_BUSSOFT().
*/

if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) {
if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES)
return; /* unsupported asic type */
}

if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB)
goto error_return; /* no further fixup necessary */

provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
if (provider == NULL) {
if (provider == NULL)
return; /* no provider registerd for this asic */
}

provider_soft = NULL;
if (provider->bus_fixup) {
if (provider->bus_fixup)
provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr);
}

if (provider_soft == NULL) {
if (provider_soft == NULL)
return; /* fixup failed or not applicable */
}

/*
* Generic bus fixup goes here. Don't reference prom_bussoft_ptr
Expand All @@ -370,12 +374,47 @@ static void sn_pci_controller_fixup(int segment, int busnum)

bus->sysdata = controller;
PCI_CONTROLLER(bus)->platform_data = provider_soft;

nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
cnode = nasid_to_cnodeid(nasid);
hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
&(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);

return;

error_return:

kfree(controller);
return;
}

void sn_bus_store_sysdata(struct pci_dev *dev)
{
struct sysdata_el *element;

element = kcalloc(1, sizeof(struct sysdata_el), GFP_KERNEL);
if (!element) {
dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__);
return;
}
element->sysdata = dev->sysdata;
list_add(&element->entry, &sn_sysdata_list);
}

void sn_bus_free_sysdata(void)
{
struct sysdata_el *element;
struct list_head *list;

sn_sysdata_free_start:
list_for_each(list, &sn_sysdata_list) {
element = list_entry(list, struct sysdata_el, entry);
list_del(&element->entry);
kfree(element->sysdata);
kfree(element);
goto sn_sysdata_free_start;
}
return;
}

/*
Expand Down Expand Up @@ -413,15 +452,16 @@ static int __init sn_pci_init(void)
ia64_max_iommu_merge_mask = ~PAGE_MASK;
sn_fixup_ionodes();
sn_irq_lh_init();
INIT_LIST_HEAD(&sn_sysdata_list);
sn_init_cpei_timer();

#ifdef CONFIG_PROC_FS
register_sn_procfs();
#endif

for (i = 0; i < PCI_BUSES_TO_SCAN; i++) {
sn_pci_controller_fixup(0, i);
}
/* busses are not known yet ... */
for (i = 0; i < PCI_BUSES_TO_SCAN; i++)
sn_pci_controller_fixup(0, i, NULL);

/*
* Generic Linux PCI Layer has created the pci_bus and pci_dev
Expand All @@ -430,9 +470,8 @@ static int __init sn_pci_init(void)
*/

while ((pci_dev =
pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL) {
pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL)
sn_pci_fixup_slot(pci_dev);
}

sn_ioif_inited = 1; /* sn I/O infrastructure now initialized */

Expand Down Expand Up @@ -474,3 +513,8 @@ cnodeid_get_geoid(cnodeid_t cnode)
}

subsys_initcall(sn_pci_init);
EXPORT_SYMBOL(sn_pci_fixup_slot);
EXPORT_SYMBOL(sn_pci_unfixup_slot);
EXPORT_SYMBOL(sn_pci_controller_fixup);
EXPORT_SYMBOL(sn_bus_store_sysdata);
EXPORT_SYMBOL(sn_bus_free_sysdata);
6 changes: 3 additions & 3 deletions arch/ia64/sn/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,6 @@ void sn_irq_fixup(struct pci_dev *pci_dev, struct sn_irq_info *sn_irq_info)
int cpu = nasid_slice_to_cpuid(nasid, slice);

pci_dev_get(pci_dev);

sn_irq_info->irq_cpuid = cpu;
sn_irq_info->irq_pciioinfo = SN_PCIDEV_INFO(pci_dev);

Expand All @@ -305,15 +304,16 @@ void sn_irq_unfixup(struct pci_dev *pci_dev)
return;

sn_irq_info = SN_PCIDEV_INFO(pci_dev)->pdi_sn_irq_info;
if (!sn_irq_info || !sn_irq_info->irq_irq)
if (!sn_irq_info || !sn_irq_info->irq_irq) {
kfree(sn_irq_info);
return;
}

unregister_intr_pda(sn_irq_info);
spin_lock(&sn_irq_info_lock);
list_del_rcu(&sn_irq_info->list);
spin_unlock(&sn_irq_info_lock);
call_rcu(&sn_irq_info->rcu, sn_irq_info_free);

pci_dev_put(pci_dev);
}

Expand Down
37 changes: 37 additions & 0 deletions arch/ia64/sn/pci/pcibr/pcibr_provider.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,40 @@
#include "xtalk/xwidgetdev.h"
#include "xtalk/hubdev.h"

int
sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp)
{
struct ia64_sal_retval ret_stuff;
uint64_t busnum;

ret_stuff.status = 0;
ret_stuff.v0 = 0;

busnum = soft->pbi_buscommon.bs_persist_busnum;
SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, (u64) busnum,
(u64) device, (u64) resp, 0, 0, 0, 0);

return (int)ret_stuff.v0;
}

int
sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
void *resp)
{
struct ia64_sal_retval ret_stuff;
uint64_t busnum;

ret_stuff.status = 0;
ret_stuff.v0 = 0;

busnum = soft->pbi_buscommon.bs_persist_busnum;
SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_DISABLE,
(u64) busnum, (u64) device, (u64) action,
(u64) resp, 0, 0, 0);

return (int)ret_stuff.v0;
}

static int sal_pcibr_error_interrupt(struct pcibus_info *soft)
{
struct ia64_sal_retval ret_stuff;
Expand Down Expand Up @@ -187,3 +221,6 @@ pcibr_init_provider(void)

return 0;
}

EXPORT_SYMBOL_GPL(sal_pcibr_slot_enable);
EXPORT_SYMBOL_GPL(sal_pcibr_slot_disable);
5 changes: 3 additions & 2 deletions drivers/pci/hotplug/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -187,9 +187,10 @@ config HOTPLUG_PCI_RPA_DLPAR

config HOTPLUG_PCI_SGI
tristate "SGI PCI Hotplug Support"
depends on HOTPLUG_PCI && IA64_SGI_SN2
depends on HOTPLUG_PCI && (IA64_SGI_SN2 || IA64_GENERIC)
help
Say Y here if you have an SGI IA64 Altix system.
Say Y here if you want to use the SGI Altix Hotplug
Driver for PCI devices.

When in doubt, say N.

Expand Down
1 change: 1 addition & 0 deletions drivers/pci/hotplug/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ obj-$(CONFIG_HOTPLUG_PCI_PCIE) += pciehp.o
obj-$(CONFIG_HOTPLUG_PCI_SHPC) += shpchp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA) += rpaphp.o
obj-$(CONFIG_HOTPLUG_PCI_RPA_DLPAR) += rpadlpar_io.o
obj-$(CONFIG_HOTPLUG_PCI_SGI) += sgi_hotplug.o

pci_hotplug-objs := pci_hotplug_core.o

Expand Down
Loading

0 comments on commit 6f354b0

Please sign in to comment.