Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
934b6519
Commit
934b6519
authored
Feb 22, 2004
by
Pat Gefre
Committed by
David Mosberger
Feb 22, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] ia64: add Altix hotplug support
parent
4ce0447a
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
656 additions
and
23 deletions
+656
-23
arch/ia64/sn/io/machvec/pci_bus_cvlink.c
arch/ia64/sn/io/machvec/pci_bus_cvlink.c
+77
-2
arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
+5
-0
arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
+414
-3
arch/ia64/sn/kernel/irq.c
arch/ia64/sn/kernel/irq.c
+43
-0
drivers/pci/hotplug/Kconfig
drivers/pci/hotplug/Kconfig
+8
-0
include/asm-ia64/sn/pci/pcibr.h
include/asm-ia64/sn/pci/pcibr.h
+69
-18
include/asm-ia64/sn/pci/pcibr_private.h
include/asm-ia64/sn/pci/pcibr_private.h
+11
-0
include/asm-ia64/sn/sn_sal.h
include/asm-ia64/sn/sn_sal.h
+29
-0
No files found.
arch/ia64/sn/io/machvec/pci_bus_cvlink.c
View file @
934b6519
...
...
@@ -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
;
}
}
...
...
arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
View file @
934b6519
...
...
@@ -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 */
}
/*
...
...
arch/ia64/sn/io/sn2/pcibr/pcibr_slot.c
View file @
934b6519
...
...
@@ -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 @@ void do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t);
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 @@ pcibr_slot_info_init(vertex_hdl_t pcibr_vhdl,
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 @@ pcibr_slot_call_device_attach(vertex_hdl_t pcibr_vhdl,
}
/* 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_slot_call_device_attach(vertex_hdl_t pcibr_vhdl,
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 @@ pcibr_slot_call_device_detach(vertex_hdl_t pcibr_vhdl,
}
/* 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,10 +1524,12 @@ pcibr_slot_call_device_detach(vertex_hdl_t pcibr_vhdl,
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
* This is a place holder routine to keep track of all the
...
...
arch/ia64/sn/kernel/irq.c
View file @
934b6519
...
...
@@ -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
)
{
...
...
drivers/pci/hotplug/Kconfig
View file @
934b6519
...
...
@@ -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
include/asm-ia64/sn/pci/pcibr.h
View file @
934b6519
...
...
@@ -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
...
...
include/asm-ia64/sn/pci/pcibr_private.h
View file @
934b6519
...
...
@@ -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
...
...
include/asm-ia64/sn/sn_sal.h
View file @
934b6519
...
...
@@ -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 */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment