public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [2.6 PATCH] Altix hotplug
@ 2004-02-20 21:11 Pat Gefre
  0 siblings, 0 replies; 8+ messages in thread
From: Pat Gefre @ 2004-02-20 21:11 UTC (permalink / raw)
  To: davidm; +Cc: linux-kernel, linux-ia64

2.6 Altix patch for kernel hotplug support

-- 

Patrick Gefre
Silicon Graphics, Inc.                     (E-Mail)  pfg@sgi.com
2750 Blue Water Rd                         (Voice)   (651) 683-3127
Eagan, MN 55121-1400                       (FAX)     (651) 683-3054



# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1656  -> 1.1657 
#	include/asm-ia64/sn/pci/pcibr_private.h	1.21    -> 1.22   
#	arch/ia64/sn/kernel/irq.c	1.18    -> 1.19   
#	drivers/pci/hotplug/Kconfig	1.12    -> 1.13   
#	arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	1.18    -> 1.19   
#	arch/ia64/sn/io/machvec/pci_bus_cvlink.c	1.35    -> 1.36   
#	include/asm-ia64/sn/pci/pcibr.h	1.13    -> 1.14   
#	include/asm-ia64/sn/sn_sal.h	1.6     -> 1.7    
#	arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	1.28    -> 1.29   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/02/19	pfg@sgi.com	1.1657
# arch/ia64/sn/io/machvec/pci_bus_cvlink.c
#     Interface functions for hot plug added:
#         sn_dma_flush_clear - called from sn_pci_unfixup_slot
#         sn_pci_unfixup_slot - called from the sn hotplug driver
# arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
#     Add an ifdef for CONFIG_HOTPLUG_PCI_SGI in a couple of blocks.
#     The use of slot_status is hotplug only
# arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
#     More hotplug support code : pcibr_slot_enable and pcibr_slot_disable are hotplug
#     driver interfaces, the others are support funcs
#     Made the use of slot_status hotplug only
# arch/ia64/sn/kernel/irq.c
#     Added unregister_pcibr_intr - a hotplug support function
# drivers/pci/hotplug/Kconfig
#     config option to enabel SGI SN2 PCI hotplug
# include/asm-ia64/sn/pci/pcibr.h
#     data structs and definitions needed for hotplug
#     removed some typedefs .....
# include/asm-ia64/sn/pci/pcibr_private.h
#     Added elements needed for hotplug
# include/asm-ia64/sn/sn_sal.h
#     Added sal call needed for hotplug - perform a 'generic' hotplug call
# --------------------------------------------
#
diff -Nru a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c
--- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	Thu Feb 19 17:12:31 2004
+++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	Thu Feb 19 17:12:31 2004
@@ -384,6 +384,80 @@
 	return 0;
 }
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+
+void
+sn_dma_flush_clear(struct sn_flush_device_list *dma_flush_list,
+                   unsigned long start, unsigned long end)
+{
+
+        int i;
+
+        dma_flush_list->pin = -1;
+        dma_flush_list->bus = -1;
+        dma_flush_list->slot = -1;
+
+        for (i = 0; i < PCI_ROM_RESOURCE; i++)
+                if ((dma_flush_list->bar_list[i].start == start) &&
+                    (dma_flush_list->bar_list[i].end == end)) {
+                        dma_flush_list->bar_list[i].start = 0;
+                        dma_flush_list->bar_list[i].end = 0;
+                        break;
+                }           
+
+}
+
+/*
+ * sn_pci_unfixup_slot() - This routine frees a slot's resources
+ * consistent with the Linux PCI abstraction layer.  Resources released
+ * back to our PCI provider include PIO maps to BAR space and interrupt
+ * objects.
+ */
+void
+sn_pci_unfixup_slot(struct pci_dev *dev)
+{
+	struct sn_device_sysdata *device_sysdata;
+	vertex_hdl_t vhdl;
+	pciio_intr_t intr_handle;
+	unsigned int irq;
+	unsigned long size;
+	int idx;
+
+	device_sysdata = SN_DEVICE_SYSDATA(dev);
+
+	vhdl = device_sysdata->vhdl;
+
+	if (device_sysdata->dma_flush_list)
+		for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+			size = dev->resource[idx].end -
+				dev->resource[idx].start;
+			if (size == 0) continue;
+
+			sn_dma_flush_clear(device_sysdata->dma_flush_list,
+				   	   dev->resource[idx].start,
+				   	   dev->resource[idx].end);
+		}
+
+	intr_handle = device_sysdata->intr_handle;
+	if (intr_handle) {
+		extern void unregister_pcibr_intr(int, pcibr_intr_t);
+		irq = intr_handle->pi_irq;
+		irqpdaindr->device_dev[irq] = NULL;
+		unregister_pcibr_intr(irq, (pcibr_intr_t) intr_handle);
+		pciio_intr_disconnect(intr_handle);
+		pciio_intr_free(intr_handle);
+	}
+
+	for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+		if (device_sysdata->pio_map[idx]) {
+			pciio_piomap_done (device_sysdata->pio_map[idx]);
+			pciio_piomap_free (device_sysdata->pio_map[idx]);
+		}
+	}
+
+}
+#endif /* CONFIG_HOTPLUG_PCI_SGI */
+
 struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS];
 
 /* Initialize the data structures for flushing write buffers after a PIO read.
@@ -534,6 +608,7 @@
 	return p;
 }
 
+
 /*
  * linux_bus_cvlink() Creates a link between the Linux PCI Bus number
  *	to the actual hardware component that it represents:
@@ -774,7 +849,7 @@
 			printk(KERN_WARNING
 				"sn_pci_fixup: sn_pci_fixup_bus fails : error %d\n",
 					ret);
-			return;
+			return 0;
 		}
 	}
 
@@ -805,7 +880,7 @@
 			printk(KERN_WARNING
 				"sn_pci_fixup: sn_pci_fixup_slot fails : error %d\n",
 					ret);
-			return;
+			return 0;
 		}
 	}
 
diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
--- a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	Thu Feb 19 17:12:31 2004
+++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	Thu Feb 19 17:12:31 2004
@@ -629,6 +629,8 @@
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
     pcibr_info->f_att_det_error = error;
+
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
 
     if (error) {
@@ -636,6 +638,7 @@
     } else {
         pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT;
     }
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 }
 
 /*
@@ -668,6 +671,7 @@
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
     pcibr_info->f_att_det_error = error;
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
 
     if (error) {
@@ -675,6 +679,7 @@
     } else {
         pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT;
     }
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 }
 
 /*
diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
--- a/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	Thu Feb 19 17:12:31 2004
+++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	Thu Feb 19 17:12:31 2004
@@ -16,6 +16,7 @@
 #include <asm/sn/pci/pcibr_private.h>
 #include <asm/sn/pci/pci_defs.h>
 #include <asm/sn/sn_private.h>
+#include <asm/sn/sn_sal.h>
 
 extern pcibr_info_t     pcibr_info_get(vertex_hdl_t);
 extern int              pcibr_widget_to_bus(vertex_hdl_t pcibr_vhdl);
@@ -58,6 +59,411 @@
 int max_splittrans_to_numbuf[MAX_SPLIT_TABLE] = {1, 2, 3, 4, 8, 12, 16, 32};
 int max_readcount_to_bufsize[MAX_READCNT_TABLE] = {512, 1024, 2048, 4096 };
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+
+/*
+ * PCI slot manipulation errors from the system controller, and their
+ * associated descriptions
+ */
+#define SYSCTL_REQERR_BASE	(-106000)
+#define SYSCTL_PCI_ERROR_BASE	(SYSCTL_REQERR_BASE - 100)
+#define SYSCTL_PCIX_ERROR_BASE	(SYSCTL_REQERR_BASE - 3000)
+
+struct sysctl_pci_error_s {
+
+    int	 	error;
+    char	*msg;
+
+} sysctl_pci_errors[] = {
+
+#define SYSCTL_PCI_UNINITIALIZED	(SYSCTL_PCI_ERROR_BASE - 0)
+    { SYSCTL_PCI_UNINITIALIZED, "module not initialized" },
+
+#define SYSCTL_PCI_UNSUPPORTED_BUS	(SYSCTL_PCI_ERROR_BASE - 1)
+    { SYSCTL_PCI_UNSUPPORTED_BUS, "unsupported bus" },
+
+#define SYSCTL_PCI_UNSUPPORTED_SLOT	(SYSCTL_PCI_ERROR_BASE - 2)
+    { SYSCTL_PCI_UNSUPPORTED_SLOT, "unsupported slot" },
+
+#define SYSCTL_PCI_POWER_NOT_OKAY	(SYSCTL_PCI_ERROR_BASE - 3)
+    { SYSCTL_PCI_POWER_NOT_OKAY, "slot power not okay" },
+
+#define SYSCTL_PCI_CARD_NOT_PRESENT	(SYSCTL_PCI_ERROR_BASE - 4)
+    { SYSCTL_PCI_CARD_NOT_PRESENT, "card not present" },
+
+#define SYSCTL_PCI_POWER_LIMIT		(SYSCTL_PCI_ERROR_BASE - 5)
+    { SYSCTL_PCI_POWER_LIMIT, "power limit reached - some cards not powered up" },
+
+#define SYSCTL_PCI_33MHZ_ON_66MHZ	(SYSCTL_PCI_ERROR_BASE - 6)
+    { SYSCTL_PCI_33MHZ_ON_66MHZ, "cannot add a 33 MHz card to an active 66 MHz bus" },
+
+#define SYSCTL_PCI_INVALID_ORDER	(SYSCTL_PCI_ERROR_BASE - 7)
+    { SYSCTL_PCI_INVALID_ORDER, "invalid reset order" },
+
+#define SYSCTL_PCI_DOWN_33MHZ		(SYSCTL_PCI_ERROR_BASE - 8)
+    { SYSCTL_PCI_DOWN_33MHZ, "cannot power down a 33 MHz card on an active bus" },
+
+#define SYSCTL_PCI_RESET_33MHZ		(SYSCTL_PCI_ERROR_BASE - 9)
+    { SYSCTL_PCI_RESET_33MHZ, "cannot reset a 33 MHz card on an active bus" },
+
+#define SYSCTL_PCI_SLOT_NOT_UP		(SYSCTL_PCI_ERROR_BASE - 10)
+    { SYSCTL_PCI_SLOT_NOT_UP, "cannot reset a slot that is not powered up" },
+
+#define SYSCTL_PCIX_UNINITIALIZED	(SYSCTL_PCIX_ERROR_BASE - 0)
+    { SYSCTL_PCIX_UNINITIALIZED, "module not initialized" },
+
+#define SYSCTL_PCIX_UNSUPPORTED_BUS	(SYSCTL_PCIX_ERROR_BASE - 1)
+    { SYSCTL_PCIX_UNSUPPORTED_BUS, "unsupported bus" },
+
+#define SYSCTL_PCIX_UNSUPPORTED_SLOT	(SYSCTL_PCIX_ERROR_BASE - 2)
+    { SYSCTL_PCIX_UNSUPPORTED_SLOT, "unsupported slot" },
+
+#define SYSCTL_PCIX_POWER_NOT_OKAY	(SYSCTL_PCIX_ERROR_BASE - 3)
+    { SYSCTL_PCIX_POWER_NOT_OKAY, "slot power not okay" },
+
+#define SYSCTL_PCIX_CARD_NOT_PRESENT	(SYSCTL_PCIX_ERROR_BASE - 4)
+    { SYSCTL_PCIX_CARD_NOT_PRESENT, "card not present" },
+
+#define SYSCTL_PCIX_POWER_LIMIT		(SYSCTL_PCIX_ERROR_BASE - 5)
+    { SYSCTL_PCIX_POWER_LIMIT, "power limit reached - some cards not powered up" },
+
+#define SYSCTL_PCIX_33MHZ_ON_66MHZ	(SYSCTL_PCIX_ERROR_BASE - 6)
+    { SYSCTL_PCIX_33MHZ_ON_66MHZ, "cannot add a 33 MHz card to an active 66 MHz bus" },
+
+#define SYSCTL_PCIX_PCI_ON_PCIX		(SYSCTL_PCIX_ERROR_BASE - 7)
+    { SYSCTL_PCIX_PCI_ON_PCIX, "cannot add a PCI card to an active PCIX bus" },
+
+#define SYSCTL_PCIX_ANYTHING_ON_133MHZ		(SYSCTL_PCIX_ERROR_BASE - 8)
+    { SYSCTL_PCIX_ANYTHING_ON_133MHZ, "cannot add any card to an active 133MHz PCIX bus" },
+
+#define SYSCTL_PCIX_X66MHZ_ON_X100MHZ		(SYSCTL_PCIX_ERROR_BASE - 9)
+    { SYSCTL_PCIX_X66MHZ_ON_X100MHZ, "cannot add a PCIX 66MHz card to an active 100MHz PCIX bus" },
+
+#define SYSCTL_PCIX_INVALID_ORDER	(SYSCTL_PCIX_ERROR_BASE - 10)
+    { SYSCTL_PCIX_INVALID_ORDER, "invalid reset order" },
+
+#define SYSCTL_PCIX_DOWN_33MHZ		(SYSCTL_PCIX_ERROR_BASE - 11)
+    { SYSCTL_PCIX_DOWN_33MHZ, "cannot power down a 33 MHz card on an active bus" },
+
+#define SYSCTL_PCIX_RESET_33MHZ		(SYSCTL_PCIX_ERROR_BASE - 12)
+    { SYSCTL_PCIX_RESET_33MHZ, "cannot reset a 33 MHz card on an active bus" },
+
+#define SYSCTL_PCIX_SLOT_NOT_UP		(SYSCTL_PCIX_ERROR_BASE - 13)
+    { SYSCTL_PCIX_SLOT_NOT_UP, "cannot reset a slot that is not powered up" },
+
+#define SYSCTL_PCIX_INVALID_BUS_SETTING	(SYSCTL_PCIX_ERROR_BASE - 14)
+    { SYSCTL_PCIX_INVALID_BUS_SETTING, "invalid bus type/speed selection (PCIX<66MHz, PCI>66MHz)" },
+
+#define SYSCTL_PCIX_INVALID_DEPENDENT_SLOT (SYSCTL_PCIX_ERROR_BASE - 15)
+    { SYSCTL_PCIX_INVALID_DEPENDENT_SLOT, "invalid dependent slot in PCI slot configuration" },
+
+#define SYSCTL_PCIX_SHARED_IDSELECT	(SYSCTL_PCIX_ERROR_BASE - 16)
+    { SYSCTL_PCIX_SHARED_IDSELECT, "cannot enable two slots sharing the same IDSELECT" },
+
+#define SYSCTL_PCIX_SLOT_DISABLED	(SYSCTL_PCIX_ERROR_BASE - 17)
+    { SYSCTL_PCIX_SLOT_DISABLED, "slot is disabled" },
+
+}; /* end sysctl_pci_errors[] */
+
+/*
+ * look up an error message for PCI operations that fail
+ */
+static void
+sysctl_pci_error_lookup(int error, char *err_msg)
+{
+    int i;
+    struct sysctl_pci_error_s *e = sysctl_pci_errors;
+    
+    for (i = 0; 
+	 i < (sizeof(sysctl_pci_errors) / sizeof(*e));
+	 i++, e++ )
+    {
+	if (e->error == error)
+	{
+	    strcpy(err_msg, e->msg);
+	    return;
+	}
+    }
+
+    sprintf(err_msg, "unrecognized PCI error type");
+}
+
+/*
+ * pcibr_slot_attach
+ *	This is a place holder routine to keep track of all the
+ *	slot-specific initialization that needs to be done.
+ *	This is usually called when we want to initialize a new
+ * 	PCI card on the bus.
+ */
+int
+pcibr_slot_attach(vertex_hdl_t pcibr_vhdl,
+		  pciio_slot_t slot,
+		  int          drv_flags,
+		  char        *l1_msg,
+                  int         *sub_errorp)
+{
+    pcibr_soft_t  pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    int		  error;
+
+    if (!(pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_POWER_ON)) {
+	uint64_t speed;
+	uint64_t mode;
+
+        /* Power-up the slot */
+        error = pcibr_slot_pwr(pcibr_vhdl, slot, PCI_REQ_SLOT_POWER_ON, l1_msg);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_L1_ERR);
+        } else {
+            pcibr_soft->bs_slot[slot].slot_status &= ~PCI_SLOT_POWER_MASK;
+            pcibr_soft->bs_slot[slot].slot_status |= PCI_SLOT_POWER_ON;
+        }
+
+	/* The speed/mode of the bus may have changed due to the hotplug */
+	speed = pcireg_speed_get(pcibr_soft);
+	mode = pcireg_mode_get(pcibr_soft);
+	pcibr_soft->bs_bridge_mode = ((speed << 1) | mode);
+
+        /*
+         * Allow cards like the Alteon Gigabit Ethernet Adapter to complete
+         * on-card initialization following the slot reset
+         */
+        set_current_state (TASK_INTERRUPTIBLE);
+        schedule_timeout (HZ);
+
+        /* Find out what is out there */
+        error = pcibr_slot_info_init(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_INFO_INIT_ERR);
+        }
+
+        /* Set up the address space for this slot in the PCI land */
+
+        error = pcibr_slot_addr_space_init(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_ADDR_INIT_ERR);
+        }
+
+	/* Allocate the PCI-X Read Buffer Attribute Registers (RBARs)*/
+	if (IS_PCIX(pcibr_soft)) {
+	    int tmp_slot;
+
+	    /* Recalculate the RBARs for all the devices on the bus.  Only
+	     * return an error if we error for the given 'slot'
+	     */
+	    pcibr_soft->bs_pcix_rbar_inuse = 0;
+	    pcibr_soft->bs_pcix_rbar_avail = NUM_RBAR;
+	    pcibr_soft->bs_pcix_rbar_percent_allowed = 
+					pcibr_pcix_rbars_calc(pcibr_soft);
+	    for (tmp_slot = pcibr_soft->bs_min_slot;
+			tmp_slot < PCIBR_NUM_SLOTS(pcibr_soft); ++tmp_slot) {
+		if (tmp_slot == slot)
+		    continue;	/* skip this 'slot', we do it below */
+                (void)pcibr_slot_pcix_rbar_init(pcibr_soft, tmp_slot);
+	    }
+
+	    error = pcibr_slot_pcix_rbar_init(pcibr_soft, slot);
+	    if (error) {
+		if (sub_errorp)
+		    *sub_errorp = error;
+		return(PCI_SLOT_RBAR_ALLOC_ERR);
+	    }
+	}
+
+        /* Setup the device register */
+        error = pcibr_slot_device_init(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_DEV_INIT_ERR);
+        }
+
+        /* Setup host/guest relations */
+        error = pcibr_slot_guest_info_init(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_GUEST_INIT_ERR);
+        }
+
+        /* Initial RRB management */
+        error = pcibr_slot_initial_rrb_alloc(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_RRB_ALLOC_ERR);
+        }
+
+    }
+
+    /* Call the device attach */
+    error = pcibr_slot_call_device_attach(pcibr_vhdl, slot, drv_flags);
+
+    if (error) {
+        if (sub_errorp)
+            *sub_errorp = error;
+        if (error == EUNATCH)
+            return(PCI_NO_DRIVER);
+        else
+            return(PCI_SLOT_DRV_ATTACH_ERR);
+    }
+
+    return(0);
+}
+
+/*
+ * pcibr_slot_enable
+ *	Enable the PCI slot for a hot-plug insert.
+ */
+int
+pcibr_slot_enable(vertex_hdl_t pcibr_vhdl, struct pcibr_slot_enable_req_s *req_p)
+{
+    pcibr_soft_t                   pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    pciio_slot_t                   slot = req_p->req_device;
+    int                            error = 0;
+
+    /* Make sure that we are dealing with a bridge device vertex */
+    if (!pcibr_soft) {
+        return(PCI_NOT_A_BRIDGE);
+    }
+
+    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HOTPLUG, pcibr_vhdl,
+                "pcibr_slot_enable: pcibr_soft=0x%lx, slot=%d, req_p=0x%lx\n",
+                pcibr_soft, slot, req_p));
+
+    /* Check for the valid slot */
+    if (!PCIBR_VALID_SLOT(pcibr_soft, slot))
+        return(PCI_NOT_A_SLOT);
+
+    if (pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_ENABLE_CMPLT) {
+        error = PCI_SLOT_ALREADY_UP;
+        goto enable_unlock;
+    }
+
+    error = pcibr_slot_attach(pcibr_vhdl, slot, NULL,
+                              req_p->req_resp.resp_l1_msg,
+			      &req_p->req_resp.resp_sub_errno);
+
+    req_p->req_resp.resp_l1_msg[PCI_L1_QSIZE] = '\0';
+
+    enable_unlock:
+
+    return(error);
+}
+
+/*
+ * pcibr_slot_disable
+ *	Disable the PCI slot for a hot-plug removal.
+ */
+int
+pcibr_slot_disable(vertex_hdl_t pcibr_vhdl, struct pcibr_slot_disable_req_s *req_p)
+{
+    pcibr_soft_t                   pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    pciio_slot_t                   slot = req_p->req_device;
+    int                            error = 0;
+    pciio_slot_t                   tmp_slot;
+
+    /* Make sure that we are dealing with a bridge device vertex */
+    if (!pcibr_soft) {
+        return(PCI_NOT_A_BRIDGE);
+    }
+
+    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HOTPLUG, pcibr_vhdl,
+                "pcibr_slot_disable: pcibr_soft=0x%lx, slot=%d, req_p=0x%lx\n",
+                pcibr_soft, slot, req_p));
+
+    /* Check for valid slot */
+    if (!PCIBR_VALID_SLOT(pcibr_soft, slot))
+        return(PCI_NOT_A_SLOT);
+
+    if ((pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_DISABLE_CMPLT) ||
+       ((pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_STATUS_MASK) == 0)) {
+        error = PCI_SLOT_ALREADY_DOWN;
+        /*
+         * RJR - Should we invoke an L1 slot power-down command just in case
+         *       a previous shut-down failed to power-down the slot?
+         */
+        goto disable_unlock;
+    }
+
+    /* Do not allow the last 33 MHz card to be removed */
+    if (IS_33MHZ(pcibr_soft)) {
+        for (tmp_slot = pcibr_soft->bs_first_slot;
+             tmp_slot <= pcibr_soft->bs_last_slot; tmp_slot++)
+            if (tmp_slot != slot)
+                if (pcibr_soft->bs_slot[tmp_slot].slot_status & PCI_SLOT_POWER_ON) {
+                    error++;
+                    break;
+                }
+        if (!error) {
+            error = PCI_EMPTY_33MHZ;
+            goto disable_unlock;
+        }
+    }
+
+    if (req_p->req_action == PCI_REQ_SLOT_ELIGIBLE)
+	return(0);
+
+    error = pcibr_slot_detach(pcibr_vhdl, slot, 1,
+                              req_p->req_resp.resp_l1_msg,
+			      &req_p->req_resp.resp_sub_errno);
+
+    req_p->req_resp.resp_l1_msg[PCI_L1_QSIZE] = '\0';
+
+    disable_unlock:
+
+    return(error);
+}
+
+/*
+ * pcibr_slot_pwr
+ *      Power-up or power-down a PCI slot.  This routines makes calls to
+ *      the L1 system controller driver which requires "external" slot#.
+ */
+int
+pcibr_slot_pwr(vertex_hdl_t pcibr_vhdl,
+               pciio_slot_t slot,
+               int          up,
+	       char        *err_msg)
+{
+    pcibr_soft_t        pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    nasid_t             nasid;
+    u64			connection_type;
+    int			rv;
+
+    nasid = NASID_GET(pcibr_soft->bs_base);
+    connection_type = SAL_SYSCTL_IO_XTALK;
+
+    rv = (int) ia64_sn_sysctl_iobrick_pci_op
+	(nasid,
+	 connection_type,
+	 (u64) pcibr_widget_to_bus(pcibr_vhdl),
+	 PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot),
+	 (up ? SAL_SYSCTL_PCI_POWER_UP : SAL_SYSCTL_PCI_POWER_DOWN));
+
+    if (!rv) {
+	/* everything's okay; no error message */
+	*err_msg = '\0';
+    }
+    else {
+	/* there was a problem; look up an appropriate error message */
+	sysctl_pci_error_lookup(rv, err_msg);
+    }
+    return rv;
+}
+
+#endif /* CONFIG_HOTPLUG_PCI_SGI */
 
 /*
  * pcibr_slot_info_init
@@ -114,7 +520,9 @@
 	return -ENODEV;
 
     slotp = &pcibr_soft->bs_slot[slot];
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     slotp->slot_status |= SLOT_POWER_UP;
+#endif
 
     vendor = 0xFFFF & idword;
     device = 0xFFFF & (idword >> 16);
@@ -1019,6 +1427,7 @@
 
     }				/* next func */
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     if (error) {
 	if ((error != ENODEV) && (error != EUNATCH) && (error != EPERM)) {
 	    pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
@@ -1028,7 +1437,7 @@
         pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
         pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT;
     }
-        
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
     return error;
 }
 
@@ -1103,7 +1512,7 @@
 
     }				/* next func */
 
-
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     if (error) {
 	if ((error != ENODEV) && (error != EUNATCH) && (error != EPERM)) {
 	    pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
@@ -1115,9 +1524,11 @@
         pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
         pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT;
     }
-        
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
     return error;
 }
+
+
 
 /*
  * pcibr_slot_detach
diff -Nru a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
--- a/arch/ia64/sn/kernel/irq.c	Thu Feb 19 17:12:31 2004
+++ b/arch/ia64/sn/kernel/irq.c	Thu Feb 19 17:12:31 2004
@@ -212,6 +212,49 @@
 }
 
 void
+unregister_pcibr_intr(int irq, pcibr_intr_t intr)
+{
+
+	struct sn_intr_list_t **prev, *curr;
+	int cpu = intr->bi_cpu;
+	int i;
+
+	if (sn_intr_list[irq] == NULL)
+		return;
+
+	prev = &sn_intr_list[irq];
+	curr = sn_intr_list[irq];
+	while (curr) {
+		if (curr->intr == intr)	 {
+			*prev = curr->next;
+			break;
+		}
+		prev = &curr->next;
+		curr = curr->next;
+	}
+
+	if (curr)
+		kfree(curr);
+
+	if (!sn_intr_list[irq]) {
+		if (pdacpu(cpu)->sn_last_irq == irq) {
+			for (i = pdacpu(cpu)->sn_last_irq - 1; i; i--)
+				if (sn_intr_list[i])
+					break;
+			pdacpu(cpu)->sn_last_irq = i;
+		}
+
+		if (pdacpu(cpu)->sn_first_irq == irq) {
+			pdacpu(cpu)->sn_first_irq = 0;
+			for (i = pdacpu(cpu)->sn_first_irq + 1; i < NR_IRQS; i++)
+				if (sn_intr_list[i])
+					pdacpu(cpu)->sn_first_irq = i;
+		}
+	}
+
+}
+
+void
 force_polled_int(void)
 {
 	int i;
diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
--- a/drivers/pci/hotplug/Kconfig	Thu Feb 19 17:12:31 2004
+++ b/drivers/pci/hotplug/Kconfig	Thu Feb 19 17:12:31 2004
@@ -122,5 +122,13 @@
 
 	  When in doubt, say N.
 
+config HOTPLUG_PCI_SGI
+	tristate "SGI PCI Hotplug Support"
+	depends on HOTPLUG_PCI && IA64_SGI_SN2
+	help
+	  Say Y here if you have an SGI IA64 Altix system.
+
+	  When in doubt, say N.
+
 endmenu
 
diff -Nru a/include/asm-ia64/sn/pci/pcibr.h b/include/asm-ia64/sn/pci/pcibr.h
--- a/include/asm-ia64/sn/pci/pcibr.h	Thu Feb 19 17:12:31 2004
+++ b/include/asm-ia64/sn/pci/pcibr.h	Thu Feb 19 17:12:31 2004
@@ -325,9 +325,27 @@
 #define PCIBR			'p'
 #define _PCIBR(x)		((PCIBR << 8) | (x))
 
-#define PCIBR_SLOT_STARTUP	_PCIBR(1)
-#define PCIBR_SLOT_SHUTDOWN     _PCIBR(2)
-#define PCIBR_SLOT_QUERY	_PCIBR(3)
+/*
+ * Bit defintions for variable slot_status in struct
+ * pcibr_soft_slot_s.  They are here so that the user
+ * hot-plug utility can interpret the slot's power
+ * status.
+ */
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+#define PCI_SLOT_ENABLE_CMPLT       0x01    
+#define PCI_SLOT_ENABLE_INCMPLT     0x02    
+#define PCI_SLOT_DISABLE_CMPLT      0x04    
+#define PCI_SLOT_DISABLE_INCMPLT    0x08    
+#define PCI_SLOT_POWER_ON           0x10    
+#define PCI_SLOT_POWER_OFF          0x20    
+#define PCI_SLOT_IS_SYS_CRITICAL    0x40    
+#define PCI_SLOT_PCIBA_LOADED       0x80    
+
+#define PCI_SLOT_STATUS_MASK        (PCI_SLOT_ENABLE_CMPLT | \
+				     PCI_SLOT_ENABLE_INCMPLT | \
+                                     PCI_SLOT_DISABLE_CMPLT | \
+				     PCI_SLOT_DISABLE_INCMPLT)
+#define PCI_SLOT_POWER_MASK         (PCI_SLOT_POWER_ON | PCI_SLOT_POWER_OFF)
 
 /*
  * Bit defintions for variable slot_status in struct
@@ -356,26 +374,20 @@
 #define FUNC_IS_SYS_CRITICAL    0x02
 
 /*
- * Structures for requesting PCI bridge information and receiving a response
+ * L1 slot power operations for PCI hot-plug
  */
-typedef struct pcibr_slot_req_s *pcibr_slot_req_t;
-typedef struct pcibr_slot_up_resp_s *pcibr_slot_up_resp_t;
-typedef struct pcibr_slot_down_resp_s *pcibr_slot_down_resp_t;
-typedef struct pcibr_slot_info_resp_s *pcibr_slot_info_resp_t;
-typedef struct pcibr_slot_func_info_resp_s *pcibr_slot_func_info_resp_t;
+#define PCI_REQ_SLOT_POWER_ON       1
+#define PCI_L1_QSIZE                128      /* our L1 message buffer size */
+
 
 #define L1_QSIZE                128      /* our L1 message buffer size */
-struct pcibr_slot_req_s {
-    int                      req_slot;
-    union {
-        pcibr_slot_up_resp_t     up;
-        pcibr_slot_down_resp_t   down;
-        pcibr_slot_info_resp_t   query;
-        void                    *any;
-    }                       req_respp;
-    int                     req_size;
+
+enum pcibr_slot_disable_action_e {
+    PCI_REQ_SLOT_ELIGIBLE,
+    PCI_REQ_SLOT_DISABLE
 };
 
+
 struct pcibr_slot_up_resp_s {
     int                     resp_sub_errno;
     char                    resp_l1_msg[L1_QSIZE + 1];
@@ -443,6 +455,45 @@
 
     } resp_func[8];
 };
+
+struct pcibr_slot_req_s {
+    int                      req_slot;
+    union {
+        enum pcibr_slot_disable_action_e up;
+        struct pcibr_slot_down_resp_s *down;
+        struct pcibr_slot_info_resp_s *query;
+        void                    *any;
+    }                       req_respp;
+    int                     req_size;
+};
+
+struct pcibr_slot_enable_resp_s {
+    int                     resp_sub_errno;
+    char                    resp_l1_msg[PCI_L1_QSIZE + 1];
+};
+
+struct pcibr_slot_disable_resp_s {
+    int                     resp_sub_errno;
+    char                    resp_l1_msg[PCI_L1_QSIZE + 1];
+};
+
+struct pcibr_slot_enable_req_s {
+    pciio_slot_t              	     req_device;
+    struct pcibr_slot_enable_resp_s  req_resp;
+};
+
+struct pcibr_slot_disable_req_s {
+    pciio_slot_t                     req_device;
+    enum pcibr_slot_disable_action_e req_action;
+    struct pcibr_slot_disable_resp_s req_resp;
+};
+
+struct pcibr_slot_info_req_s {
+    pciio_slot_t              	     req_device;
+    struct pcibr_slot_info_resp_s    req_resp;
+};
+
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 
 
 /*
diff -Nru a/include/asm-ia64/sn/pci/pcibr_private.h b/include/asm-ia64/sn/pci/pcibr_private.h
--- a/include/asm-ia64/sn/pci/pcibr_private.h	Thu Feb 19 17:12:31 2004
+++ b/include/asm-ia64/sn/pci/pcibr_private.h	Thu Feb 19 17:12:31 2004
@@ -475,6 +475,12 @@
     
     vertex_hdl_t	    bs_noslot_conn;	/* NO-SLOT connection point */
     pcibr_info_t	    bs_noslot_info;
+
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+    /* Linux PCI bus structure pointer */
+    struct pci_bus         *bs_pci_bus;
+#endif
+
     struct pcibr_soft_slot_s {
 	/* information we keep about each CFG slot */
 
@@ -492,8 +498,13 @@
 	pciio_slot_t            host_slot;
 	vertex_hdl_t		slot_conn;
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
         /* PCI Hot-Plug status word */
         int 			slot_status;
+
+	/* PCI Hot-Plug core structure pointer */
+	struct hotplug_slot    *bss_hotplug_slot;
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 
 	/* Potentially several connection points
 	 * for this slot. bss_ninfo is how many,
diff -Nru a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
--- a/include/asm-ia64/sn/sn_sal.h	Thu Feb 19 17:12:31 2004
+++ b/include/asm-ia64/sn/sn_sal.h	Thu Feb 19 17:12:31 2004
@@ -58,6 +58,7 @@
 #define  SN_SAL_MEMPROTECT                         0x0200003e
 #define  SN_SAL_SYSCTL_FRU_CAPTURE		   0x0200003f
 
+#define  SN_SAL_SYSCTL_IOBRICK_PCI_OP		   0x02000042	// reentrant
 
 /*
  * Service-specific constants
@@ -72,6 +73,16 @@
 #define SAL_CONSOLE_INTR_XMIT	1	/* output interrupt */
 #define SAL_CONSOLE_INTR_RECV	2	/* input interrupt */
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+/* power up / power down / reset a PCI slot or bus */
+#define SAL_SYSCTL_PCI_POWER_UP         0
+#define SAL_SYSCTL_PCI_POWER_DOWN       1
+#define SAL_SYSCTL_PCI_RESET            2
+
+/* what type of I/O brick? */
+#define SAL_SYSCTL_IO_XTALK	0       /* connected via a compute node */
+
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 
 /*
  * SN_SAL_GET_PARTITION_ADDR return constants
@@ -639,6 +650,24 @@
         if (isrv.status)
                 return 0;
         return isrv.v0;
+}
+
+/*
+ * Performs an operation on a PCI bus or slot -- power up, power down
+ * or reset.
+ */
+static inline u64
+ia64_sn_sysctl_iobrick_pci_op(nasid_t n, u64 connection_type, 
+			      u64 bus, slotid_t slot, 
+			      u64 action)
+{
+	struct ia64_sal_retval rv = {0, 0, 0, 0};
+
+	SAL_CALL_NOLOCK(rv, SN_SAL_SYSCTL_IOBRICK_PCI_OP, connection_type, n, action,
+		 bus, (u64) slot, 0, 0);
+	if (rv.status)
+	    	return rv.v0;
+	return 0;
 }
 
 #endif /* _ASM_IA64_SN_SN_SAL_H */

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [2.6 PATCH] Altix hotplug
@ 2004-02-23 14:55 Pat Gefre
  2004-02-23 20:23 ` Greg KH
  2004-02-23 21:04 ` Greg KH
  0 siblings, 2 replies; 8+ messages in thread
From: Pat Gefre @ 2004-02-23 14:55 UTC (permalink / raw)
  To: davidm; +Cc: linux-kernel, linux-ia64


2.6 Altix patch for kernel hotplug support

-- 

Patrick Gefre
Silicon Graphics, Inc.                     (E-Mail)  pfg@sgi.com
2750 Blue Water Rd                         (Voice)   (651) 683-3127
Eagan, MN 55121-1400                       (FAX)     (651) 683-3054




# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.1656  -> 1.1657 
#	include/asm-ia64/sn/pci/pcibr_private.h	1.21    -> 1.22   
#	arch/ia64/sn/kernel/irq.c	1.18    -> 1.19   
#	drivers/pci/hotplug/Kconfig	1.12    -> 1.13   
#	arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	1.18    -> 1.19   
#	arch/ia64/sn/io/machvec/pci_bus_cvlink.c	1.35    -> 1.36   
#	include/asm-ia64/sn/pci/pcibr.h	1.13    -> 1.14   
#	include/asm-ia64/sn/sn_sal.h	1.6     -> 1.7    
#	arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	1.28    -> 1.29   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 04/02/19	pfg@sgi.com	1.1657
# arch/ia64/sn/io/machvec/pci_bus_cvlink.c
#     Interface functions for hot plug added:
#         sn_dma_flush_clear - called from sn_pci_unfixup_slot
#         sn_pci_unfixup_slot - called from the sn hotplug driver
# arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
#     Add an ifdef for CONFIG_HOTPLUG_PCI_SGI in a couple of blocks.
#     The use of slot_status is hotplug only
# arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
#     More hotplug support code : pcibr_slot_enable and pcibr_slot_disable are hotplug
#     driver interfaces, the others are support funcs
#     Made the use of slot_status hotplug only
# arch/ia64/sn/kernel/irq.c
#     Added unregister_pcibr_intr - a hotplug support function
# drivers/pci/hotplug/Kconfig
#     config option to enabel SGI SN2 PCI hotplug
# include/asm-ia64/sn/pci/pcibr.h
#     data structs and definitions needed for hotplug
#     removed some typedefs .....
# include/asm-ia64/sn/pci/pcibr_private.h
#     Added elements needed for hotplug
# include/asm-ia64/sn/sn_sal.h
#     Added sal call needed for hotplug - perform a 'generic' hotplug call
# --------------------------------------------
#
diff -Nru a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c
--- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	Thu Feb 19 17:12:31 2004
+++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c	Thu Feb 19 17:12:31 2004
@@ -384,6 +384,80 @@
 	return 0;
 }
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+
+void
+sn_dma_flush_clear(struct sn_flush_device_list *dma_flush_list,
+                   unsigned long start, unsigned long end)
+{
+
+        int i;
+
+        dma_flush_list->pin = -1;
+        dma_flush_list->bus = -1;
+        dma_flush_list->slot = -1;
+
+        for (i = 0; i < PCI_ROM_RESOURCE; i++)
+                if ((dma_flush_list->bar_list[i].start == start) &&
+                    (dma_flush_list->bar_list[i].end == end)) {
+                        dma_flush_list->bar_list[i].start = 0;
+                        dma_flush_list->bar_list[i].end = 0;
+                        break;
+                }           
+
+}
+
+/*
+ * sn_pci_unfixup_slot() - This routine frees a slot's resources
+ * consistent with the Linux PCI abstraction layer.  Resources released
+ * back to our PCI provider include PIO maps to BAR space and interrupt
+ * objects.
+ */
+void
+sn_pci_unfixup_slot(struct pci_dev *dev)
+{
+	struct sn_device_sysdata *device_sysdata;
+	vertex_hdl_t vhdl;
+	pciio_intr_t intr_handle;
+	unsigned int irq;
+	unsigned long size;
+	int idx;
+
+	device_sysdata = SN_DEVICE_SYSDATA(dev);
+
+	vhdl = device_sysdata->vhdl;
+
+	if (device_sysdata->dma_flush_list)
+		for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+			size = dev->resource[idx].end -
+				dev->resource[idx].start;
+			if (size == 0) continue;
+
+			sn_dma_flush_clear(device_sysdata->dma_flush_list,
+				   	   dev->resource[idx].start,
+				   	   dev->resource[idx].end);
+		}
+
+	intr_handle = device_sysdata->intr_handle;
+	if (intr_handle) {
+		extern void unregister_pcibr_intr(int, pcibr_intr_t);
+		irq = intr_handle->pi_irq;
+		irqpdaindr->device_dev[irq] = NULL;
+		unregister_pcibr_intr(irq, (pcibr_intr_t) intr_handle);
+		pciio_intr_disconnect(intr_handle);
+		pciio_intr_free(intr_handle);
+	}
+
+	for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) {
+		if (device_sysdata->pio_map[idx]) {
+			pciio_piomap_done (device_sysdata->pio_map[idx]);
+			pciio_piomap_free (device_sysdata->pio_map[idx]);
+		}
+	}
+
+}
+#endif /* CONFIG_HOTPLUG_PCI_SGI */
+
 struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS];
 
 /* Initialize the data structures for flushing write buffers after a PIO read.
@@ -534,6 +608,7 @@
 	return p;
 }
 
+
 /*
  * linux_bus_cvlink() Creates a link between the Linux PCI Bus number
  *	to the actual hardware component that it represents:
@@ -774,7 +849,7 @@
 			printk(KERN_WARNING
 				"sn_pci_fixup: sn_pci_fixup_bus fails : error %d\n",
 					ret);
-			return;
+			return 0;
 		}
 	}
 
@@ -805,7 +880,7 @@
 			printk(KERN_WARNING
 				"sn_pci_fixup: sn_pci_fixup_slot fails : error %d\n",
 					ret);
-			return;
+			return 0;
 		}
 	}
 
diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
--- a/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	Thu Feb 19 17:12:31 2004
+++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c	Thu Feb 19 17:12:31 2004
@@ -629,6 +629,8 @@
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
     pcibr_info->f_att_det_error = error;
+
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
 
     if (error) {
@@ -636,6 +638,7 @@
     } else {
         pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT;
     }
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 }
 
 /*
@@ -668,6 +671,7 @@
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
     pcibr_info->f_att_det_error = error;
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
 
     if (error) {
@@ -675,6 +679,7 @@
     } else {
         pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT;
     }
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 }
 
 /*
diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
--- a/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	Thu Feb 19 17:12:31 2004
+++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c	Thu Feb 19 17:12:31 2004
@@ -16,6 +16,7 @@
 #include <asm/sn/pci/pcibr_private.h>
 #include <asm/sn/pci/pci_defs.h>
 #include <asm/sn/sn_private.h>
+#include <asm/sn/sn_sal.h>
 
 extern pcibr_info_t     pcibr_info_get(vertex_hdl_t);
 extern int              pcibr_widget_to_bus(vertex_hdl_t pcibr_vhdl);
@@ -58,6 +59,411 @@
 int max_splittrans_to_numbuf[MAX_SPLIT_TABLE] = {1, 2, 3, 4, 8, 12, 16, 32};
 int max_readcount_to_bufsize[MAX_READCNT_TABLE] = {512, 1024, 2048, 4096 };
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+
+/*
+ * PCI slot manipulation errors from the system controller, and their
+ * associated descriptions
+ */
+#define SYSCTL_REQERR_BASE	(-106000)
+#define SYSCTL_PCI_ERROR_BASE	(SYSCTL_REQERR_BASE - 100)
+#define SYSCTL_PCIX_ERROR_BASE	(SYSCTL_REQERR_BASE - 3000)
+
+struct sysctl_pci_error_s {
+
+    int	 	error;
+    char	*msg;
+
+} sysctl_pci_errors[] = {
+
+#define SYSCTL_PCI_UNINITIALIZED	(SYSCTL_PCI_ERROR_BASE - 0)
+    { SYSCTL_PCI_UNINITIALIZED, "module not initialized" },
+
+#define SYSCTL_PCI_UNSUPPORTED_BUS	(SYSCTL_PCI_ERROR_BASE - 1)
+    { SYSCTL_PCI_UNSUPPORTED_BUS, "unsupported bus" },
+
+#define SYSCTL_PCI_UNSUPPORTED_SLOT	(SYSCTL_PCI_ERROR_BASE - 2)
+    { SYSCTL_PCI_UNSUPPORTED_SLOT, "unsupported slot" },
+
+#define SYSCTL_PCI_POWER_NOT_OKAY	(SYSCTL_PCI_ERROR_BASE - 3)
+    { SYSCTL_PCI_POWER_NOT_OKAY, "slot power not okay" },
+
+#define SYSCTL_PCI_CARD_NOT_PRESENT	(SYSCTL_PCI_ERROR_BASE - 4)
+    { SYSCTL_PCI_CARD_NOT_PRESENT, "card not present" },
+
+#define SYSCTL_PCI_POWER_LIMIT		(SYSCTL_PCI_ERROR_BASE - 5)
+    { SYSCTL_PCI_POWER_LIMIT, "power limit reached - some cards not powered up" },
+
+#define SYSCTL_PCI_33MHZ_ON_66MHZ	(SYSCTL_PCI_ERROR_BASE - 6)
+    { SYSCTL_PCI_33MHZ_ON_66MHZ, "cannot add a 33 MHz card to an active 66 MHz bus" },
+
+#define SYSCTL_PCI_INVALID_ORDER	(SYSCTL_PCI_ERROR_BASE - 7)
+    { SYSCTL_PCI_INVALID_ORDER, "invalid reset order" },
+
+#define SYSCTL_PCI_DOWN_33MHZ		(SYSCTL_PCI_ERROR_BASE - 8)
+    { SYSCTL_PCI_DOWN_33MHZ, "cannot power down a 33 MHz card on an active bus" },
+
+#define SYSCTL_PCI_RESET_33MHZ		(SYSCTL_PCI_ERROR_BASE - 9)
+    { SYSCTL_PCI_RESET_33MHZ, "cannot reset a 33 MHz card on an active bus" },
+
+#define SYSCTL_PCI_SLOT_NOT_UP		(SYSCTL_PCI_ERROR_BASE - 10)
+    { SYSCTL_PCI_SLOT_NOT_UP, "cannot reset a slot that is not powered up" },
+
+#define SYSCTL_PCIX_UNINITIALIZED	(SYSCTL_PCIX_ERROR_BASE - 0)
+    { SYSCTL_PCIX_UNINITIALIZED, "module not initialized" },
+
+#define SYSCTL_PCIX_UNSUPPORTED_BUS	(SYSCTL_PCIX_ERROR_BASE - 1)
+    { SYSCTL_PCIX_UNSUPPORTED_BUS, "unsupported bus" },
+
+#define SYSCTL_PCIX_UNSUPPORTED_SLOT	(SYSCTL_PCIX_ERROR_BASE - 2)
+    { SYSCTL_PCIX_UNSUPPORTED_SLOT, "unsupported slot" },
+
+#define SYSCTL_PCIX_POWER_NOT_OKAY	(SYSCTL_PCIX_ERROR_BASE - 3)
+    { SYSCTL_PCIX_POWER_NOT_OKAY, "slot power not okay" },
+
+#define SYSCTL_PCIX_CARD_NOT_PRESENT	(SYSCTL_PCIX_ERROR_BASE - 4)
+    { SYSCTL_PCIX_CARD_NOT_PRESENT, "card not present" },
+
+#define SYSCTL_PCIX_POWER_LIMIT		(SYSCTL_PCIX_ERROR_BASE - 5)
+    { SYSCTL_PCIX_POWER_LIMIT, "power limit reached - some cards not powered up" },
+
+#define SYSCTL_PCIX_33MHZ_ON_66MHZ	(SYSCTL_PCIX_ERROR_BASE - 6)
+    { SYSCTL_PCIX_33MHZ_ON_66MHZ, "cannot add a 33 MHz card to an active 66 MHz bus" },
+
+#define SYSCTL_PCIX_PCI_ON_PCIX		(SYSCTL_PCIX_ERROR_BASE - 7)
+    { SYSCTL_PCIX_PCI_ON_PCIX, "cannot add a PCI card to an active PCIX bus" },
+
+#define SYSCTL_PCIX_ANYTHING_ON_133MHZ		(SYSCTL_PCIX_ERROR_BASE - 8)
+    { SYSCTL_PCIX_ANYTHING_ON_133MHZ, "cannot add any card to an active 133MHz PCIX bus" },
+
+#define SYSCTL_PCIX_X66MHZ_ON_X100MHZ		(SYSCTL_PCIX_ERROR_BASE - 9)
+    { SYSCTL_PCIX_X66MHZ_ON_X100MHZ, "cannot add a PCIX 66MHz card to an active 100MHz PCIX bus" },
+
+#define SYSCTL_PCIX_INVALID_ORDER	(SYSCTL_PCIX_ERROR_BASE - 10)
+    { SYSCTL_PCIX_INVALID_ORDER, "invalid reset order" },
+
+#define SYSCTL_PCIX_DOWN_33MHZ		(SYSCTL_PCIX_ERROR_BASE - 11)
+    { SYSCTL_PCIX_DOWN_33MHZ, "cannot power down a 33 MHz card on an active bus" },
+
+#define SYSCTL_PCIX_RESET_33MHZ		(SYSCTL_PCIX_ERROR_BASE - 12)
+    { SYSCTL_PCIX_RESET_33MHZ, "cannot reset a 33 MHz card on an active bus" },
+
+#define SYSCTL_PCIX_SLOT_NOT_UP		(SYSCTL_PCIX_ERROR_BASE - 13)
+    { SYSCTL_PCIX_SLOT_NOT_UP, "cannot reset a slot that is not powered up" },
+
+#define SYSCTL_PCIX_INVALID_BUS_SETTING	(SYSCTL_PCIX_ERROR_BASE - 14)
+    { SYSCTL_PCIX_INVALID_BUS_SETTING, "invalid bus type/speed selection (PCIX<66MHz, PCI>66MHz)" },
+
+#define SYSCTL_PCIX_INVALID_DEPENDENT_SLOT (SYSCTL_PCIX_ERROR_BASE - 15)
+    { SYSCTL_PCIX_INVALID_DEPENDENT_SLOT, "invalid dependent slot in PCI slot configuration" },
+
+#define SYSCTL_PCIX_SHARED_IDSELECT	(SYSCTL_PCIX_ERROR_BASE - 16)
+    { SYSCTL_PCIX_SHARED_IDSELECT, "cannot enable two slots sharing the same IDSELECT" },
+
+#define SYSCTL_PCIX_SLOT_DISABLED	(SYSCTL_PCIX_ERROR_BASE - 17)
+    { SYSCTL_PCIX_SLOT_DISABLED, "slot is disabled" },
+
+}; /* end sysctl_pci_errors[] */
+
+/*
+ * look up an error message for PCI operations that fail
+ */
+static void
+sysctl_pci_error_lookup(int error, char *err_msg)
+{
+    int i;
+    struct sysctl_pci_error_s *e = sysctl_pci_errors;
+    
+    for (i = 0; 
+	 i < (sizeof(sysctl_pci_errors) / sizeof(*e));
+	 i++, e++ )
+    {
+	if (e->error == error)
+	{
+	    strcpy(err_msg, e->msg);
+	    return;
+	}
+    }
+
+    sprintf(err_msg, "unrecognized PCI error type");
+}
+
+/*
+ * pcibr_slot_attach
+ *	This is a place holder routine to keep track of all the
+ *	slot-specific initialization that needs to be done.
+ *	This is usually called when we want to initialize a new
+ * 	PCI card on the bus.
+ */
+int
+pcibr_slot_attach(vertex_hdl_t pcibr_vhdl,
+		  pciio_slot_t slot,
+		  int          drv_flags,
+		  char        *l1_msg,
+                  int         *sub_errorp)
+{
+    pcibr_soft_t  pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    int		  error;
+
+    if (!(pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_POWER_ON)) {
+	uint64_t speed;
+	uint64_t mode;
+
+        /* Power-up the slot */
+        error = pcibr_slot_pwr(pcibr_vhdl, slot, PCI_REQ_SLOT_POWER_ON, l1_msg);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_L1_ERR);
+        } else {
+            pcibr_soft->bs_slot[slot].slot_status &= ~PCI_SLOT_POWER_MASK;
+            pcibr_soft->bs_slot[slot].slot_status |= PCI_SLOT_POWER_ON;
+        }
+
+	/* The speed/mode of the bus may have changed due to the hotplug */
+	speed = pcireg_speed_get(pcibr_soft);
+	mode = pcireg_mode_get(pcibr_soft);
+	pcibr_soft->bs_bridge_mode = ((speed << 1) | mode);
+
+        /*
+         * Allow cards like the Alteon Gigabit Ethernet Adapter to complete
+         * on-card initialization following the slot reset
+         */
+        set_current_state (TASK_INTERRUPTIBLE);
+        schedule_timeout (HZ);
+
+        /* Find out what is out there */
+        error = pcibr_slot_info_init(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_INFO_INIT_ERR);
+        }
+
+        /* Set up the address space for this slot in the PCI land */
+
+        error = pcibr_slot_addr_space_init(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_ADDR_INIT_ERR);
+        }
+
+	/* Allocate the PCI-X Read Buffer Attribute Registers (RBARs)*/
+	if (IS_PCIX(pcibr_soft)) {
+	    int tmp_slot;
+
+	    /* Recalculate the RBARs for all the devices on the bus.  Only
+	     * return an error if we error for the given 'slot'
+	     */
+	    pcibr_soft->bs_pcix_rbar_inuse = 0;
+	    pcibr_soft->bs_pcix_rbar_avail = NUM_RBAR;
+	    pcibr_soft->bs_pcix_rbar_percent_allowed = 
+					pcibr_pcix_rbars_calc(pcibr_soft);
+	    for (tmp_slot = pcibr_soft->bs_min_slot;
+			tmp_slot < PCIBR_NUM_SLOTS(pcibr_soft); ++tmp_slot) {
+		if (tmp_slot == slot)
+		    continue;	/* skip this 'slot', we do it below */
+                (void)pcibr_slot_pcix_rbar_init(pcibr_soft, tmp_slot);
+	    }
+
+	    error = pcibr_slot_pcix_rbar_init(pcibr_soft, slot);
+	    if (error) {
+		if (sub_errorp)
+		    *sub_errorp = error;
+		return(PCI_SLOT_RBAR_ALLOC_ERR);
+	    }
+	}
+
+        /* Setup the device register */
+        error = pcibr_slot_device_init(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_DEV_INIT_ERR);
+        }
+
+        /* Setup host/guest relations */
+        error = pcibr_slot_guest_info_init(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_GUEST_INIT_ERR);
+        }
+
+        /* Initial RRB management */
+        error = pcibr_slot_initial_rrb_alloc(pcibr_vhdl, slot);
+
+        if (error) {
+            if (sub_errorp)
+                *sub_errorp = error;
+            return(PCI_SLOT_RRB_ALLOC_ERR);
+        }
+
+    }
+
+    /* Call the device attach */
+    error = pcibr_slot_call_device_attach(pcibr_vhdl, slot, drv_flags);
+
+    if (error) {
+        if (sub_errorp)
+            *sub_errorp = error;
+        if (error == EUNATCH)
+            return(PCI_NO_DRIVER);
+        else
+            return(PCI_SLOT_DRV_ATTACH_ERR);
+    }
+
+    return(0);
+}
+
+/*
+ * pcibr_slot_enable
+ *	Enable the PCI slot for a hot-plug insert.
+ */
+int
+pcibr_slot_enable(vertex_hdl_t pcibr_vhdl, struct pcibr_slot_enable_req_s *req_p)
+{
+    pcibr_soft_t                   pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    pciio_slot_t                   slot = req_p->req_device;
+    int                            error = 0;
+
+    /* Make sure that we are dealing with a bridge device vertex */
+    if (!pcibr_soft) {
+        return(PCI_NOT_A_BRIDGE);
+    }
+
+    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HOTPLUG, pcibr_vhdl,
+                "pcibr_slot_enable: pcibr_soft=0x%lx, slot=%d, req_p=0x%lx\n",
+                pcibr_soft, slot, req_p));
+
+    /* Check for the valid slot */
+    if (!PCIBR_VALID_SLOT(pcibr_soft, slot))
+        return(PCI_NOT_A_SLOT);
+
+    if (pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_ENABLE_CMPLT) {
+        error = PCI_SLOT_ALREADY_UP;
+        goto enable_unlock;
+    }
+
+    error = pcibr_slot_attach(pcibr_vhdl, slot, NULL,
+                              req_p->req_resp.resp_l1_msg,
+			      &req_p->req_resp.resp_sub_errno);
+
+    req_p->req_resp.resp_l1_msg[PCI_L1_QSIZE] = '\0';
+
+    enable_unlock:
+
+    return(error);
+}
+
+/*
+ * pcibr_slot_disable
+ *	Disable the PCI slot for a hot-plug removal.
+ */
+int
+pcibr_slot_disable(vertex_hdl_t pcibr_vhdl, struct pcibr_slot_disable_req_s *req_p)
+{
+    pcibr_soft_t                   pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    pciio_slot_t                   slot = req_p->req_device;
+    int                            error = 0;
+    pciio_slot_t                   tmp_slot;
+
+    /* Make sure that we are dealing with a bridge device vertex */
+    if (!pcibr_soft) {
+        return(PCI_NOT_A_BRIDGE);
+    }
+
+    PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HOTPLUG, pcibr_vhdl,
+                "pcibr_slot_disable: pcibr_soft=0x%lx, slot=%d, req_p=0x%lx\n",
+                pcibr_soft, slot, req_p));
+
+    /* Check for valid slot */
+    if (!PCIBR_VALID_SLOT(pcibr_soft, slot))
+        return(PCI_NOT_A_SLOT);
+
+    if ((pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_DISABLE_CMPLT) ||
+       ((pcibr_soft->bs_slot[slot].slot_status & PCI_SLOT_STATUS_MASK) == 0)) {
+        error = PCI_SLOT_ALREADY_DOWN;
+        /*
+         * RJR - Should we invoke an L1 slot power-down command just in case
+         *       a previous shut-down failed to power-down the slot?
+         */
+        goto disable_unlock;
+    }
+
+    /* Do not allow the last 33 MHz card to be removed */
+    if (IS_33MHZ(pcibr_soft)) {
+        for (tmp_slot = pcibr_soft->bs_first_slot;
+             tmp_slot <= pcibr_soft->bs_last_slot; tmp_slot++)
+            if (tmp_slot != slot)
+                if (pcibr_soft->bs_slot[tmp_slot].slot_status & PCI_SLOT_POWER_ON) {
+                    error++;
+                    break;
+                }
+        if (!error) {
+            error = PCI_EMPTY_33MHZ;
+            goto disable_unlock;
+        }
+    }
+
+    if (req_p->req_action == PCI_REQ_SLOT_ELIGIBLE)
+	return(0);
+
+    error = pcibr_slot_detach(pcibr_vhdl, slot, 1,
+                              req_p->req_resp.resp_l1_msg,
+			      &req_p->req_resp.resp_sub_errno);
+
+    req_p->req_resp.resp_l1_msg[PCI_L1_QSIZE] = '\0';
+
+    disable_unlock:
+
+    return(error);
+}
+
+/*
+ * pcibr_slot_pwr
+ *      Power-up or power-down a PCI slot.  This routines makes calls to
+ *      the L1 system controller driver which requires "external" slot#.
+ */
+int
+pcibr_slot_pwr(vertex_hdl_t pcibr_vhdl,
+               pciio_slot_t slot,
+               int          up,
+	       char        *err_msg)
+{
+    pcibr_soft_t        pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    nasid_t             nasid;
+    u64			connection_type;
+    int			rv;
+
+    nasid = NASID_GET(pcibr_soft->bs_base);
+    connection_type = SAL_SYSCTL_IO_XTALK;
+
+    rv = (int) ia64_sn_sysctl_iobrick_pci_op
+	(nasid,
+	 connection_type,
+	 (u64) pcibr_widget_to_bus(pcibr_vhdl),
+	 PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot),
+	 (up ? SAL_SYSCTL_PCI_POWER_UP : SAL_SYSCTL_PCI_POWER_DOWN));
+
+    if (!rv) {
+	/* everything's okay; no error message */
+	*err_msg = '\0';
+    }
+    else {
+	/* there was a problem; look up an appropriate error message */
+	sysctl_pci_error_lookup(rv, err_msg);
+    }
+    return rv;
+}
+
+#endif /* CONFIG_HOTPLUG_PCI_SGI */
 
 /*
  * pcibr_slot_info_init
@@ -114,7 +520,9 @@
 	return -ENODEV;
 
     slotp = &pcibr_soft->bs_slot[slot];
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     slotp->slot_status |= SLOT_POWER_UP;
+#endif
 
     vendor = 0xFFFF & idword;
     device = 0xFFFF & (idword >> 16);
@@ -1019,6 +1427,7 @@
 
     }				/* next func */
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     if (error) {
 	if ((error != ENODEV) && (error != EUNATCH) && (error != EPERM)) {
 	    pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
@@ -1028,7 +1437,7 @@
         pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
         pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT;
     }
-        
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
     return error;
 }
 
@@ -1103,7 +1512,7 @@
 
     }				/* next func */
 
-
+#ifdef CONFIG_HOTPLUG_PCI_SGI
     if (error) {
 	if ((error != ENODEV) && (error != EUNATCH) && (error != EPERM)) {
 	    pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
@@ -1115,9 +1524,11 @@
         pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
         pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT;
     }
-        
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
     return error;
 }
+
+
 
 /*
  * pcibr_slot_detach
diff -Nru a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c
--- a/arch/ia64/sn/kernel/irq.c	Thu Feb 19 17:12:31 2004
+++ b/arch/ia64/sn/kernel/irq.c	Thu Feb 19 17:12:31 2004
@@ -212,6 +212,49 @@
 }
 
 void
+unregister_pcibr_intr(int irq, pcibr_intr_t intr)
+{
+
+	struct sn_intr_list_t **prev, *curr;
+	int cpu = intr->bi_cpu;
+	int i;
+
+	if (sn_intr_list[irq] == NULL)
+		return;
+
+	prev = &sn_intr_list[irq];
+	curr = sn_intr_list[irq];
+	while (curr) {
+		if (curr->intr == intr)	 {
+			*prev = curr->next;
+			break;
+		}
+		prev = &curr->next;
+		curr = curr->next;
+	}
+
+	if (curr)
+		kfree(curr);
+
+	if (!sn_intr_list[irq]) {
+		if (pdacpu(cpu)->sn_last_irq == irq) {
+			for (i = pdacpu(cpu)->sn_last_irq - 1; i; i--)
+				if (sn_intr_list[i])
+					break;
+			pdacpu(cpu)->sn_last_irq = i;
+		}
+
+		if (pdacpu(cpu)->sn_first_irq == irq) {
+			pdacpu(cpu)->sn_first_irq = 0;
+			for (i = pdacpu(cpu)->sn_first_irq + 1; i < NR_IRQS; i++)
+				if (sn_intr_list[i])
+					pdacpu(cpu)->sn_first_irq = i;
+		}
+	}
+
+}
+
+void
 force_polled_int(void)
 {
 	int i;
diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
--- a/drivers/pci/hotplug/Kconfig	Thu Feb 19 17:12:31 2004
+++ b/drivers/pci/hotplug/Kconfig	Thu Feb 19 17:12:31 2004
@@ -122,5 +122,13 @@
 
 	  When in doubt, say N.
 
+config HOTPLUG_PCI_SGI
+	tristate "SGI PCI Hotplug Support"
+	depends on HOTPLUG_PCI && IA64_SGI_SN2
+	help
+	  Say Y here if you have an SGI IA64 Altix system.
+
+	  When in doubt, say N.
+
 endmenu
 
diff -Nru a/include/asm-ia64/sn/pci/pcibr.h b/include/asm-ia64/sn/pci/pcibr.h
--- a/include/asm-ia64/sn/pci/pcibr.h	Thu Feb 19 17:12:31 2004
+++ b/include/asm-ia64/sn/pci/pcibr.h	Thu Feb 19 17:12:31 2004
@@ -325,9 +325,27 @@
 #define PCIBR			'p'
 #define _PCIBR(x)		((PCIBR << 8) | (x))
 
-#define PCIBR_SLOT_STARTUP	_PCIBR(1)
-#define PCIBR_SLOT_SHUTDOWN     _PCIBR(2)
-#define PCIBR_SLOT_QUERY	_PCIBR(3)
+/*
+ * Bit defintions for variable slot_status in struct
+ * pcibr_soft_slot_s.  They are here so that the user
+ * hot-plug utility can interpret the slot's power
+ * status.
+ */
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+#define PCI_SLOT_ENABLE_CMPLT       0x01    
+#define PCI_SLOT_ENABLE_INCMPLT     0x02    
+#define PCI_SLOT_DISABLE_CMPLT      0x04    
+#define PCI_SLOT_DISABLE_INCMPLT    0x08    
+#define PCI_SLOT_POWER_ON           0x10    
+#define PCI_SLOT_POWER_OFF          0x20    
+#define PCI_SLOT_IS_SYS_CRITICAL    0x40    
+#define PCI_SLOT_PCIBA_LOADED       0x80    
+
+#define PCI_SLOT_STATUS_MASK        (PCI_SLOT_ENABLE_CMPLT | \
+				     PCI_SLOT_ENABLE_INCMPLT | \
+                                     PCI_SLOT_DISABLE_CMPLT | \
+				     PCI_SLOT_DISABLE_INCMPLT)
+#define PCI_SLOT_POWER_MASK         (PCI_SLOT_POWER_ON | PCI_SLOT_POWER_OFF)
 
 /*
  * Bit defintions for variable slot_status in struct
@@ -356,26 +374,20 @@
 #define FUNC_IS_SYS_CRITICAL    0x02
 
 /*
- * Structures for requesting PCI bridge information and receiving a response
+ * L1 slot power operations for PCI hot-plug
  */
-typedef struct pcibr_slot_req_s *pcibr_slot_req_t;
-typedef struct pcibr_slot_up_resp_s *pcibr_slot_up_resp_t;
-typedef struct pcibr_slot_down_resp_s *pcibr_slot_down_resp_t;
-typedef struct pcibr_slot_info_resp_s *pcibr_slot_info_resp_t;
-typedef struct pcibr_slot_func_info_resp_s *pcibr_slot_func_info_resp_t;
+#define PCI_REQ_SLOT_POWER_ON       1
+#define PCI_L1_QSIZE                128      /* our L1 message buffer size */
+
 
 #define L1_QSIZE                128      /* our L1 message buffer size */
-struct pcibr_slot_req_s {
-    int                      req_slot;
-    union {
-        pcibr_slot_up_resp_t     up;
-        pcibr_slot_down_resp_t   down;
-        pcibr_slot_info_resp_t   query;
-        void                    *any;
-    }                       req_respp;
-    int                     req_size;
+
+enum pcibr_slot_disable_action_e {
+    PCI_REQ_SLOT_ELIGIBLE,
+    PCI_REQ_SLOT_DISABLE
 };
 
+
 struct pcibr_slot_up_resp_s {
     int                     resp_sub_errno;
     char                    resp_l1_msg[L1_QSIZE + 1];
@@ -443,6 +455,45 @@
 
     } resp_func[8];
 };
+
+struct pcibr_slot_req_s {
+    int                      req_slot;
+    union {
+        enum pcibr_slot_disable_action_e up;
+        struct pcibr_slot_down_resp_s *down;
+        struct pcibr_slot_info_resp_s *query;
+        void                    *any;
+    }                       req_respp;
+    int                     req_size;
+};
+
+struct pcibr_slot_enable_resp_s {
+    int                     resp_sub_errno;
+    char                    resp_l1_msg[PCI_L1_QSIZE + 1];
+};
+
+struct pcibr_slot_disable_resp_s {
+    int                     resp_sub_errno;
+    char                    resp_l1_msg[PCI_L1_QSIZE + 1];
+};
+
+struct pcibr_slot_enable_req_s {
+    pciio_slot_t              	     req_device;
+    struct pcibr_slot_enable_resp_s  req_resp;
+};
+
+struct pcibr_slot_disable_req_s {
+    pciio_slot_t                     req_device;
+    enum pcibr_slot_disable_action_e req_action;
+    struct pcibr_slot_disable_resp_s req_resp;
+};
+
+struct pcibr_slot_info_req_s {
+    pciio_slot_t              	     req_device;
+    struct pcibr_slot_info_resp_s    req_resp;
+};
+
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 
 
 /*
diff -Nru a/include/asm-ia64/sn/pci/pcibr_private.h b/include/asm-ia64/sn/pci/pcibr_private.h
--- a/include/asm-ia64/sn/pci/pcibr_private.h	Thu Feb 19 17:12:31 2004
+++ b/include/asm-ia64/sn/pci/pcibr_private.h	Thu Feb 19 17:12:31 2004
@@ -475,6 +475,12 @@
     
     vertex_hdl_t	    bs_noslot_conn;	/* NO-SLOT connection point */
     pcibr_info_t	    bs_noslot_info;
+
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+    /* Linux PCI bus structure pointer */
+    struct pci_bus         *bs_pci_bus;
+#endif
+
     struct pcibr_soft_slot_s {
 	/* information we keep about each CFG slot */
 
@@ -492,8 +498,13 @@
 	pciio_slot_t            host_slot;
 	vertex_hdl_t		slot_conn;
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
         /* PCI Hot-Plug status word */
         int 			slot_status;
+
+	/* PCI Hot-Plug core structure pointer */
+	struct hotplug_slot    *bss_hotplug_slot;
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 
 	/* Potentially several connection points
 	 * for this slot. bss_ninfo is how many,
diff -Nru a/include/asm-ia64/sn/sn_sal.h b/include/asm-ia64/sn/sn_sal.h
--- a/include/asm-ia64/sn/sn_sal.h	Thu Feb 19 17:12:31 2004
+++ b/include/asm-ia64/sn/sn_sal.h	Thu Feb 19 17:12:31 2004
@@ -58,6 +58,7 @@
 #define  SN_SAL_MEMPROTECT                         0x0200003e
 #define  SN_SAL_SYSCTL_FRU_CAPTURE		   0x0200003f
 
+#define  SN_SAL_SYSCTL_IOBRICK_PCI_OP		   0x02000042	// reentrant
 
 /*
  * Service-specific constants
@@ -72,6 +73,16 @@
 #define SAL_CONSOLE_INTR_XMIT	1	/* output interrupt */
 #define SAL_CONSOLE_INTR_RECV	2	/* input interrupt */
 
+#ifdef CONFIG_HOTPLUG_PCI_SGI
+/* power up / power down / reset a PCI slot or bus */
+#define SAL_SYSCTL_PCI_POWER_UP         0
+#define SAL_SYSCTL_PCI_POWER_DOWN       1
+#define SAL_SYSCTL_PCI_RESET            2
+
+/* what type of I/O brick? */
+#define SAL_SYSCTL_IO_XTALK	0       /* connected via a compute node */
+
+#endif	/* CONFIG_HOTPLUG_PCI_SGI */
 
 /*
  * SN_SAL_GET_PARTITION_ADDR return constants
@@ -639,6 +650,24 @@
         if (isrv.status)
                 return 0;
         return isrv.v0;
+}
+
+/*
+ * Performs an operation on a PCI bus or slot -- power up, power down
+ * or reset.
+ */
+static inline u64
+ia64_sn_sysctl_iobrick_pci_op(nasid_t n, u64 connection_type, 
+			      u64 bus, slotid_t slot, 
+			      u64 action)
+{
+	struct ia64_sal_retval rv = {0, 0, 0, 0};
+
+	SAL_CALL_NOLOCK(rv, SN_SAL_SYSCTL_IOBRICK_PCI_OP, connection_type, n, action,
+		 bus, (u64) slot, 0, 0);
+	if (rv.status)
+	    	return rv.v0;
+	return 0;
 }
 
 #endif /* _ASM_IA64_SN_SN_SAL_H */

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6 PATCH] Altix hotplug
  2004-02-23 14:55 [2.6 PATCH] Altix hotplug Pat Gefre
@ 2004-02-23 20:23 ` Greg KH
  2004-02-24 19:12   ` Pat Gefre
  2004-02-23 21:04 ` Greg KH
  1 sibling, 1 reply; 8+ messages in thread
From: Greg KH @ 2004-02-23 20:23 UTC (permalink / raw)
  To: Pat Gefre; +Cc: davidm, linux-kernel, linux-ia64

On Mon, Feb 23, 2004 at 08:55:14AM -0600, Pat Gefre wrote:
> 
> 2.6 Altix patch for kernel hotplug support

You mean "PCI hotplug support" right?

If so, how?  I do not see a single call to pci_hp_register() or friends
here.  What is the userspace interface to your pci hotplug system?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6 PATCH] Altix hotplug
  2004-02-23 14:55 [2.6 PATCH] Altix hotplug Pat Gefre
  2004-02-23 20:23 ` Greg KH
@ 2004-02-23 21:04 ` Greg KH
  2004-02-24 19:16   ` Pat Gefre
  1 sibling, 1 reply; 8+ messages in thread
From: Greg KH @ 2004-02-23 21:04 UTC (permalink / raw)
  To: Pat Gefre; +Cc: davidm, linux-kernel, linux-ia64

On Mon, Feb 23, 2004 at 08:55:14AM -0600, Pat Gefre wrote:
> +#define SYSCTL_PCI_UNINITIALIZED	(SYSCTL_PCI_ERROR_BASE - 0)
> +    { SYSCTL_PCI_UNINITIALIZED, "module not initialized" },

What are you going to do with this large table of strings?  I see where
you copy them to somewhere, but don't see anything beyond that.

Are we missing a huge piece of the puzzle?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6 PATCH] Altix hotplug
  2004-02-23 20:23 ` Greg KH
@ 2004-02-24 19:12   ` Pat Gefre
  2004-02-24 19:40     ` Greg KH
  0 siblings, 1 reply; 8+ messages in thread
From: Pat Gefre @ 2004-02-24 19:12 UTC (permalink / raw)
  To: Greg KH; +Cc: Pat Gefre, davidm, linux-kernel, linux-ia64

On Mon, 23 Feb 2004, Greg KH wrote:

+ On Mon, Feb 23, 2004 at 08:55:14AM -0600, Pat Gefre wrote:
+ > 
+ > 2.6 Altix patch for kernel hotplug support
+ 
+ You mean "PCI hotplug support" right?

Yes.


+ 
+ If so, how?  I do not see a single call to pci_hp_register() or friends
+ here.  What is the userspace interface to your pci hotplug system?
+ 

We have a hotplug driver - not included in this update - this is just
the kernel code.

-- Pat


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6 PATCH] Altix hotplug
  2004-02-23 21:04 ` Greg KH
@ 2004-02-24 19:16   ` Pat Gefre
  2004-02-24 21:38     ` Greg KH
  0 siblings, 1 reply; 8+ messages in thread
From: Pat Gefre @ 2004-02-24 19:16 UTC (permalink / raw)
  To: Greg KH; +Cc: Pat Gefre, davidm, linux-kernel, linux-ia64

On Mon, 23 Feb 2004, Greg KH wrote:

+ On Mon, Feb 23, 2004 at 08:55:14AM -0600, Pat Gefre wrote:
+ > +#define SYSCTL_PCI_UNINITIALIZED	(SYSCTL_PCI_ERROR_BASE - 0)
+ > +    { SYSCTL_PCI_UNINITIALIZED, "module not initialized" },
+ 
+ What are you going to do with this large table of strings?  I see where
+ you copy them to somewhere, but don't see anything beyond that.
+ 
+ Are we missing a huge piece of the puzzle?

Greg,

They are used in sysctl_pci_error_lookup(), which is called
pcibr_slot_pwr(), which is the code to put a device on-line. It all
traces back to the slot_enable call that is made from the hot plug
driver (which is not included in this mod).

-- Pat


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6 PATCH] Altix hotplug
  2004-02-24 19:12   ` Pat Gefre
@ 2004-02-24 19:40     ` Greg KH
  0 siblings, 0 replies; 8+ messages in thread
From: Greg KH @ 2004-02-24 19:40 UTC (permalink / raw)
  To: Pat Gefre; +Cc: davidm, linux-kernel, linux-ia64

On Tue, Feb 24, 2004 at 01:12:14PM -0600, Pat Gefre wrote:
> We have a hotplug driver - not included in this update - this is just
> the kernel code.

How about posting both pieces so we can try to figure out how they are
intregrated.  Without that there is no way to judge this patch alone.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [2.6 PATCH] Altix hotplug
  2004-02-24 19:16   ` Pat Gefre
@ 2004-02-24 21:38     ` Greg KH
  0 siblings, 0 replies; 8+ messages in thread
From: Greg KH @ 2004-02-24 21:38 UTC (permalink / raw)
  To: Pat Gefre; +Cc: davidm, linux-kernel, linux-ia64

On Tue, Feb 24, 2004 at 01:16:14PM -0600, Pat Gefre wrote:
> On Mon, 23 Feb 2004, Greg KH wrote:
> 
> + On Mon, Feb 23, 2004 at 08:55:14AM -0600, Pat Gefre wrote:
> + > +#define SYSCTL_PCI_UNINITIALIZED	(SYSCTL_PCI_ERROR_BASE - 0)
> + > +    { SYSCTL_PCI_UNINITIALIZED, "module not initialized" },
> + 
> + What are you going to do with this large table of strings?  I see where
> + you copy them to somewhere, but don't see anything beyond that.
> + 
> + Are we missing a huge piece of the puzzle?
> 
> Greg,
> 
> They are used in sysctl_pci_error_lookup(), which is called
> pcibr_slot_pwr(), which is the code to put a device on-line. It all
> traces back to the slot_enable call that is made from the hot plug
> driver (which is not included in this mod).

Ok, as stated before, please post both pieces so we can see if it even
makes sense for you to be splitting things up in this way (you realize
that no other pci hotplug driver needs to do it in this manner, right?)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2004-02-24 21:41 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-23 14:55 [2.6 PATCH] Altix hotplug Pat Gefre
2004-02-23 20:23 ` Greg KH
2004-02-24 19:12   ` Pat Gefre
2004-02-24 19:40     ` Greg KH
2004-02-23 21:04 ` Greg KH
2004-02-24 19:16   ` Pat Gefre
2004-02-24 21:38     ` Greg KH
  -- strict thread matches above, loose matches on Subject: below --
2004-02-20 21:11 Pat Gefre

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox