Commit 934b6519 authored by Pat Gefre's avatar Pat Gefre Committed by David Mosberger

[PATCH] ia64: add Altix hotplug support

parent 4ce0447a
......@@ -384,6 +384,80 @@ sn_pci_fixup_slot(struct pci_dev *dev)
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 @@ sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int
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 @@ sn_pci_init (void)
printk(KERN_WARNING
"sn_pci_fixup: sn_pci_fixup_bus fails : error %d\n",
ret);
return;
return 0;
}
}
......@@ -805,7 +880,7 @@ sn_pci_init (void)
printk(KERN_WARNING
"sn_pci_fixup: sn_pci_fixup_slot fails : error %d\n",
ret);
return;
return 0;
}
}
......
......@@ -629,6 +629,8 @@ pcibr_driver_reg_callback(vertex_hdl_t pconn_vhdl,
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 @@ pcibr_driver_reg_callback(vertex_hdl_t pconn_vhdl,
} else {
pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT;
}
#endif /* CONFIG_HOTPLUG_PCI_SGI */
}
/*
......@@ -668,6 +671,7 @@ pcibr_driver_unreg_callback(vertex_hdl_t pconn_vhdl,
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 @@ pcibr_driver_unreg_callback(vertex_hdl_t pconn_vhdl,
} else {
pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT;
}
#endif /* CONFIG_HOTPLUG_PCI_SGI */
}
/*
......
This diff is collapsed.
......@@ -211,6 +211,49 @@ register_pcibr_intr(int irq, pcibr_intr_t intr)
}
}
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)
{
......
......@@ -122,5 +122,13 @@ config HOTPLUG_PCI_CPCI_GENERIC
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
......@@ -325,9 +325,27 @@ extern int pcibr_asic_rev(vertex_hdl_t);
#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 @@ extern int pcibr_asic_rev(vertex_hdl_t);
#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];
......@@ -444,6 +456,45 @@ struct pcibr_slot_info_resp_s {
} 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 */
/*
* PCI specific errors, interpreted by pciconfig command
......
......@@ -475,6 +475,12 @@ struct pcibr_soft_s {
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,9 +498,14 @@ struct pcibr_soft_s {
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,
* and bss_infos is a pointer to
......
......@@ -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
......@@ -641,4 +652,22 @@ ia64_sn_fru_capture(void)
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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment