Commit ce65fb43 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/i2c-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents b0f79d02 59f73759
...@@ -80,6 +80,7 @@ EXPORT_SYMBOL(acpi_get_current_resources); ...@@ -80,6 +80,7 @@ EXPORT_SYMBOL(acpi_get_current_resources);
EXPORT_SYMBOL(acpi_get_possible_resources); EXPORT_SYMBOL(acpi_get_possible_resources);
EXPORT_SYMBOL(acpi_walk_resources); EXPORT_SYMBOL(acpi_walk_resources);
EXPORT_SYMBOL(acpi_set_current_resources); EXPORT_SYMBOL(acpi_set_current_resources);
EXPORT_SYMBOL(acpi_resource_to_address64);
EXPORT_SYMBOL(acpi_enable_event); EXPORT_SYMBOL(acpi_enable_event);
EXPORT_SYMBOL(acpi_disable_event); EXPORT_SYMBOL(acpi_disable_event);
EXPORT_SYMBOL(acpi_clear_event); EXPORT_SYMBOL(acpi_clear_event);
......
...@@ -61,7 +61,7 @@ config HOTPLUG_PCI_IBM ...@@ -61,7 +61,7 @@ config HOTPLUG_PCI_IBM
config HOTPLUG_PCI_ACPI config HOTPLUG_PCI_ACPI
tristate "ACPI PCI Hotplug driver" tristate "ACPI PCI Hotplug driver"
depends on ACPI && HOTPLUG_PCI depends on ACPI_BUS && HOTPLUG_PCI
help help
Say Y here if you have a system that supports PCI Hotplug using Say Y here if you have a system that supports PCI Hotplug using
ACPI. ACPI.
......
...@@ -806,6 +806,7 @@ static int enable_device (struct acpiphp_slot *slot) ...@@ -806,6 +806,7 @@ static int enable_device (struct acpiphp_slot *slot)
struct list_head *l; struct list_head *l;
struct acpiphp_func *func; struct acpiphp_func *func;
int retval = 0; int retval = 0;
int num;
if (slot->flags & SLOT_ENABLED) if (slot->flags & SLOT_ENABLED)
goto err_exit; goto err_exit;
...@@ -825,7 +826,10 @@ static int enable_device (struct acpiphp_slot *slot) ...@@ -825,7 +826,10 @@ static int enable_device (struct acpiphp_slot *slot)
goto err_exit; goto err_exit;
/* returned `dev' is the *first function* only! */ /* returned `dev' is the *first function* only! */
dev = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0)); num = pci_scan_slot(slot->bridge->pci_bus, PCI_DEVFN(slot->device, 0));
if (num)
pci_bus_add_devices(slot->bridge->pci_bus);
dev = pci_find_slot(slot->bridge->bus, PCI_DEVFN(slot->device, 0));
if (!dev) { if (!dev) {
err("No new device found\n"); err("No new device found\n");
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include "pci_hotplug.h" #include "pci_hotplug.h"
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <asm/io.h> /* for read? and write? functions */ #include <asm/io.h> /* for read? and write? functions */
#include <linux/delay.h> /* for delays */
#if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE) #if !defined(CONFIG_HOTPLUG_PCI_COMPAQ_MODULE)
#define MY_NAME "cpqphp.o" #define MY_NAME "cpqphp.o"
...@@ -146,6 +146,10 @@ struct ctrl_reg { /* offset */ ...@@ -146,6 +146,10 @@ struct ctrl_reg { /* offset */
u8 reserved11; /* 0x2b */ u8 reserved11; /* 0x2b */
u8 slot_SERR; /* 0x2c */ u8 slot_SERR; /* 0x2c */
u8 slot_power; /* 0x2d */ u8 slot_power; /* 0x2d */
u8 reserved12; /* 0x2e */
u8 reserved13; /* 0x2f */
u8 next_curr_freq; /* 0x30 */
u8 reset_freq_mode; /* 0x31 */
} __attribute__ ((packed)); } __attribute__ ((packed));
/* offsets to the controller registers based on the above structure layout */ /* offsets to the controller registers based on the above structure layout */
...@@ -173,6 +177,8 @@ enum ctrl_offsets { ...@@ -173,6 +177,8 @@ enum ctrl_offsets {
CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11), CTRL_RESERVED11 = offsetof(struct ctrl_reg, reserved11),
SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR), SLOT_SERR = offsetof(struct ctrl_reg, slot_SERR),
SLOT_POWER = offsetof(struct ctrl_reg, slot_power), SLOT_POWER = offsetof(struct ctrl_reg, slot_power),
NEXT_CURR_FREQ = offsetof(struct ctrl_reg, next_curr_freq),
RESET_FREQ_MODE = offsetof(struct ctrl_reg, reset_freq_mode),
}; };
struct hrt { struct hrt {
...@@ -294,12 +300,11 @@ struct controller { ...@@ -294,12 +300,11 @@ struct controller {
struct pci_resource *bus_head; struct pci_resource *bus_head;
struct pci_dev *pci_dev; struct pci_dev *pci_dev;
struct pci_bus *pci_bus; struct pci_bus *pci_bus;
struct proc_dir_entry* proc_entry;
struct proc_dir_entry* proc_entry2;
struct event_info event_queue[10]; struct event_info event_queue[10];
struct slot *slot; struct slot *slot;
u8 next_event; u8 next_event;
u8 interrupt; u8 interrupt;
u8 cfgspc_irq;
u8 bus; /* bus number for the pci hotplug controller */ u8 bus; /* bus number for the pci hotplug controller */
u8 rev; u8 rev;
u8 slot_device_offset; u8 slot_device_offset;
...@@ -316,8 +321,6 @@ struct controller { ...@@ -316,8 +321,6 @@ struct controller {
u8 pcix_speed_capability; /* PCI-X */ u8 pcix_speed_capability; /* PCI-X */
u8 pcix_support; /* PCI-X */ u8 pcix_support; /* PCI-X */
u16 vendor_id; u16 vendor_id;
char proc_name[20];
char proc_name2[20];
struct work_struct int_task_event; struct work_struct int_task_event;
wait_queue_head_t queue; /* sleep & wake process */ wait_queue_head_t queue; /* sleep & wake process */
}; };
...@@ -344,6 +347,7 @@ struct resource_lists { ...@@ -344,6 +347,7 @@ struct resource_lists {
#define PCI_SUB_HPC_ID2 0xA2F8 #define PCI_SUB_HPC_ID2 0xA2F8
#define PCI_SUB_HPC_ID3 0xA2F9 #define PCI_SUB_HPC_ID3 0xA2F9
#define PCI_SUB_HPC_ID_INTC 0xA2FA #define PCI_SUB_HPC_ID_INTC 0xA2FA
#define PCI_SUB_HPC_ID4 0xA2FD
#define INT_BUTTON_IGNORE 0 #define INT_BUTTON_IGNORE 0
#define INT_PRESENCE_ON 1 #define INT_PRESENCE_ON 1
...@@ -436,7 +440,7 @@ extern int cpqhp_return_board_resources (struct pci_func * func, struct resource ...@@ -436,7 +440,7 @@ extern int cpqhp_return_board_resources (struct pci_func * func, struct resource
extern void cpqhp_destroy_resource_list (struct resource_lists * resources); extern void cpqhp_destroy_resource_list (struct resource_lists * resources);
extern int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func); extern int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func);
extern int cpqhp_unconfigure_device (struct pci_func* func); extern int cpqhp_unconfigure_device (struct pci_func* func);
extern struct slot *cpqhp_find_slot (struct controller *ctrl, u8 device);
/* Global variables */ /* Global variables */
extern int cpqhp_debug; extern int cpqhp_debug;
...@@ -564,6 +568,7 @@ static inline void green_LED_blink (struct controller *ctrl, u8 slot) ...@@ -564,6 +568,7 @@ static inline void green_LED_blink (struct controller *ctrl, u8 slot)
u32 led_control; u32 led_control;
led_control = readl(ctrl->hpc_reg + LED_CONTROL); led_control = readl(ctrl->hpc_reg + LED_CONTROL);
led_control &= ~(0x0101L << slot);
led_control |= (0x0001L << slot); led_control |= (0x0001L << slot);
writel(led_control, ctrl->hpc_reg + LED_CONTROL); writel(led_control, ctrl->hpc_reg + LED_CONTROL);
} }
...@@ -605,14 +610,63 @@ static inline u8 read_slot_enable (struct controller *ctrl) ...@@ -605,14 +610,63 @@ static inline u8 read_slot_enable (struct controller *ctrl)
} }
/*
* get_controller_speed - find the current frequency/mode of controller.
*
* @ctrl: controller to get frequency/mode for.
*
* Returns controller speed.
*
*/
static inline u8 get_controller_speed (struct controller *ctrl) static inline u8 get_controller_speed (struct controller *ctrl)
{ {
u16 misc; u8 curr_freq;
u16 misc;
misc = readw(ctrl->hpc_reg + MISC);
return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz; if (ctrl->pcix_support) {
curr_freq = readb(ctrl->hpc_reg + NEXT_CURR_FREQ);
if ((curr_freq & 0xB0) == 0xB0)
return PCI_SPEED_133MHz_PCIX;
if ((curr_freq & 0xA0) == 0xA0)
return PCI_SPEED_100MHz_PCIX;
if ((curr_freq & 0x90) == 0x90)
return PCI_SPEED_66MHz_PCIX;
if (curr_freq & 0x10)
return PCI_SPEED_66MHz;
return PCI_SPEED_33MHz;
}
misc = readw(ctrl->hpc_reg + MISC);
return (misc & 0x0800) ? PCI_SPEED_66MHz : PCI_SPEED_33MHz;
} }
/*
* get_adapter_speed - find the max supported frequency/mode of adapter.
*
* @ctrl: hotplug controller.
* @hp_slot: hotplug slot where adapter is installed.
*
* Returns adapter speed.
*
*/
static inline u8 get_adapter_speed (struct controller *ctrl, u8 hp_slot)
{
u32 temp_dword = readl(ctrl->hpc_reg + NON_INT_INPUT);
dbg("slot: %d, PCIXCAP: %8x\n", hp_slot, temp_dword);
if (ctrl->pcix_support) {
if (temp_dword & (0x10000 << hp_slot))
return PCI_SPEED_133MHz_PCIX;
if (temp_dword & (0x100 << hp_slot))
return PCI_SPEED_66MHz_PCIX;
}
if (temp_dword & (0x01 << hp_slot))
return PCI_SPEED_66MHz;
return PCI_SPEED_33MHz;
}
static inline void enable_slot_power (struct controller *ctrl, u8 slot) static inline void enable_slot_power (struct controller *ctrl, u8 slot)
{ {
...@@ -721,5 +775,138 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl) ...@@ -721,5 +775,138 @@ static inline int wait_for_ctrl_irq (struct controller *ctrl)
return retval; return retval;
} }
/**
* set_controller_speed - set the frequency and/or mode of a specific
* controller segment.
*
* @ctrl: controller to change frequency/mode for.
* @adapter_speed: the speed of the adapter we want to match.
* @hp_slot: the slot number where the adapter is installed.
*
* Returns 0 if we successfully change frequency and/or mode to match the
* adapter speed.
*
*/
static inline u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)
{
struct slot *slot;
u8 reg;
u8 slot_power = readb(ctrl->hpc_reg + SLOT_POWER);
u16 reg16;
u32 leds = readl(ctrl->hpc_reg + LED_CONTROL);
if (ctrl->speed == adapter_speed)
return 0;
/* We don't allow freq/mode changes if we find another adapter running
* in another slot on this controller */
for(slot = ctrl->slot; slot; slot = slot->next) {
if (slot->device == (hp_slot + ctrl->slot_device_offset))
continue;
if (!slot->hotplug_slot && !slot->hotplug_slot->info)
continue;
if (slot->hotplug_slot->info->adapter_status == 0)
continue;
/* If another adapter is running on the same segment but at a
* lower speed/mode, we allow the new adapter to function at
* this rate if supported */
if (ctrl->speed < adapter_speed)
return 0;
return 1;
}
/* If the controller doesn't support freq/mode changes and the
* controller is running at a higher mode, we bail */
if ((ctrl->speed > adapter_speed) && (!ctrl->pcix_speed_capability))
return 1;
/* But we allow the adapter to run at a lower rate if possible */
if ((ctrl->speed < adapter_speed) && (!ctrl->pcix_speed_capability))
return 0;
/* We try to set the max speed supported by both the adapter and
* controller */
if (ctrl->speed_capability < adapter_speed) {
if (ctrl->speed == ctrl->speed_capability)
return 0;
adapter_speed = ctrl->speed_capability;
}
writel(0x0L, ctrl->hpc_reg + LED_CONTROL);
writeb(0x00, ctrl->hpc_reg + SLOT_ENABLE);
set_SOGO(ctrl);
wait_for_ctrl_irq(ctrl);
if (adapter_speed != PCI_SPEED_133MHz_PCIX)
reg = 0xF5;
else
reg = 0xF4;
pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
reg16 = readw(ctrl->hpc_reg + NEXT_CURR_FREQ);
reg16 &= ~0x000F;
switch(adapter_speed) {
case(PCI_SPEED_133MHz_PCIX):
reg = 0x75;
reg16 |= 0xB;
break;
case(PCI_SPEED_100MHz_PCIX):
reg = 0x74;
reg16 |= 0xA;
break;
case(PCI_SPEED_66MHz_PCIX):
reg = 0x73;
reg16 |= 0x9;
break;
case(PCI_SPEED_66MHz):
reg = 0x73;
reg16 |= 0x1;
break;
default: /* 33MHz PCI 2.2 */
reg = 0x71;
break;
}
reg16 |= 0xB << 12;
writew(reg16, ctrl->hpc_reg + NEXT_CURR_FREQ);
mdelay(5);
/* Reenable interrupts */
writel(0, ctrl->hpc_reg + INT_MASK);
pci_write_config_byte(ctrl->pci_dev, 0x41, reg);
/* Restart state machine */
reg = ~0xF;
pci_read_config_byte(ctrl->pci_dev, 0x43, &reg);
pci_write_config_byte(ctrl->pci_dev, 0x43, reg);
/* Only if mode change...*/
if (((ctrl->speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
((ctrl->speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz)))
set_SOGO(ctrl);
wait_for_ctrl_irq(ctrl);
mdelay(1100);
/* Restore LED/Slot state */
writel(leds, ctrl->hpc_reg + LED_CONTROL);
writeb(slot_power, ctrl->hpc_reg + SLOT_ENABLE);
set_SOGO(ctrl);
wait_for_ctrl_irq(ctrl);
ctrl->speed = adapter_speed;
slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
info("Successfully changed frequency/mode for adapter in slot %d\n",
slot->number);
return 0;
}
#endif #endif
...@@ -24,6 +24,9 @@ ...@@ -24,6 +24,9 @@
* *
* Send feedback to <greg@kroah.com> * Send feedback to <greg@kroah.com>
* *
* Jan 12, 2003 - Added 66/100/133MHz PCI-X support,
* Torben Mathiasen <torben.mathiasen@hp.com>
*
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -57,7 +60,7 @@ static void *cpqhp_rom_start; ...@@ -57,7 +60,7 @@ static void *cpqhp_rom_start;
static u8 power_mode; static u8 power_mode;
static int debug; static int debug;
#define DRIVER_VERSION "0.9.6" #define DRIVER_VERSION "0.9.7"
#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>" #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"
#define DRIVER_DESC "Compaq Hot Plug PCI Controller Driver" #define DRIVER_DESC "Compaq Hot Plug PCI Controller Driver"
...@@ -835,6 +838,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -835,6 +838,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
u8 hp_slot = 0; u8 hp_slot = 0;
u8 device; u8 device;
u8 rev; u8 rev;
u8 bus_cap;
u16 temp_word; u16 temp_word;
u16 vendor_id; u16 vendor_id;
u16 subsystem_vid; u16 subsystem_vid;
...@@ -896,6 +900,39 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -896,6 +900,39 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
switch (subsystem_vid) { switch (subsystem_vid) {
case PCI_VENDOR_ID_COMPAQ: case PCI_VENDOR_ID_COMPAQ:
if (rev >= 0x13) { /* CIOBX */
ctrl->push_flag = 1;
ctrl->slot_switch_type = 1; // Switch is present
ctrl->push_button = 1; // Pushbutton is present
ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
ctrl->defeature_PHP = 1; // PHP is supported
ctrl->pcix_support = 1; // PCI-X supported
ctrl->pcix_speed_capability = 1;
pci_read_config_byte(pdev, 0x41, &bus_cap);
if (bus_cap & 0x80) {
dbg("bus max supports 133MHz PCI-X\n");
ctrl->speed_capability = PCI_SPEED_133MHz_PCIX;
break;
}
if (bus_cap & 0x40) {
dbg("bus max supports 100MHz PCI-X\n");
ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
break;
}
if (bus_cap & 20) {
dbg("bus max supports 66MHz PCI-X\n");
ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
break;
}
if (bus_cap & 10) {
dbg("bus max supports 66MHz PCI\n");
ctrl->speed_capability = PCI_SPEED_66MHz;
break;
}
break;
}
switch (subsystem_deviceid) { switch (subsystem_deviceid) {
case PCI_SUB_HPC_ID: case PCI_SUB_HPC_ID:
/* Original 6500/7000 implementation */ /* Original 6500/7000 implementation */
...@@ -939,8 +976,18 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -939,8 +976,18 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ctrl->pcix_support = 0; // PCI-X not supported ctrl->pcix_support = 0; // PCI-X not supported
ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported ctrl->pcix_speed_capability = 0; // N/A since PCI-X not supported
break; break;
case PCI_SUB_HPC_ID4:
/* First PCI-X implementation, 100MHz */
ctrl->push_flag = 1;
ctrl->slot_switch_type = 1; // Switch is present
ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
ctrl->push_button = 1; // Pushbutton is present
ctrl->pci_config_space = 1; // Index/data access to working registers 0 = not supported, 1 = supported
ctrl->defeature_PHP = 1; // PHP is supported
ctrl->pcix_support = 1; // PCI-X supported
ctrl->pcix_speed_capability = 0;
break;
default: default:
// TODO: Add SSIDs for CPQ systems that support PCI-X
err(msg_HPC_not_supported); err(msg_HPC_not_supported);
rc = -ENODEV; rc = -ENODEV;
goto err_free_ctrl; goto err_free_ctrl;
...@@ -1029,7 +1076,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1029,7 +1076,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number); info("Initializing the PCI hot plug controller residing on PCI bus %d\n", pdev->bus->number);
dbg ("Hotplug controller capabilities:\n"); dbg ("Hotplug controller capabilities:\n");
dbg (" speed_capability %s\n", ctrl->speed_capability == PCI_SPEED_33MHz ? "33MHz" : "66Mhz"); dbg (" speed_capability %d\n", ctrl->speed_capability);
dbg (" slot_switch_type %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present"); dbg (" slot_switch_type %s\n", ctrl->slot_switch_type == 0 ? "no switch" : "switch present");
dbg (" defeature_PHP %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported"); dbg (" defeature_PHP %s\n", ctrl->defeature_PHP == 0 ? "PHP not supported" : "PHP supported");
dbg (" alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported"); dbg (" alternate_base_address %s\n", ctrl->alternate_base_address == 0 ? "not supported" : "supported");
...@@ -1082,7 +1129,6 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1082,7 +1129,6 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
} }
// Check for 66Mhz operation // Check for 66Mhz operation
// TODO: Add PCI-X support
ctrl->speed = get_controller_speed(ctrl); ctrl->speed = get_controller_speed(ctrl);
...@@ -1119,6 +1165,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1119,6 +1165,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
// The next line is required for cpqhp_find_available_resources // The next line is required for cpqhp_find_available_resources
ctrl->interrupt = pdev->irq; ctrl->interrupt = pdev->irq;
ctrl->cfgspc_irq = 0;
pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ctrl->cfgspc_irq);
rc = cpqhp_find_available_resources(ctrl, cpqhp_rom_start); rc = cpqhp_find_available_resources(ctrl, cpqhp_rom_start);
ctrl->add_support = !rc; ctrl->add_support = !rc;
if (rc) { if (rc) {
......
...@@ -136,9 +136,9 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl) ...@@ -136,9 +136,9 @@ static u8 handle_switch_change(u8 change, struct controller * ctrl)
/* /*
* find_slot * cpqhp_find_slot
*/ */
static inline struct slot *find_slot (struct controller * ctrl, u8 device) struct slot *cpqhp_find_slot (struct controller * ctrl, u8 device)
{ {
struct slot *slot; struct slot *slot;
...@@ -187,7 +187,7 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl) ...@@ -187,7 +187,7 @@ static u8 handle_presence_change(u16 change, struct controller * ctrl)
rc++; rc++;
p_slot = find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4)); p_slot = cpqhp_find_slot(ctrl, hp_slot + (readb(ctrl->hpc_reg + SLOT_MASK) >> 4));
if (!p_slot) if (!p_slot)
return 0; return 0;
...@@ -920,6 +920,7 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data, struct pt_regs *regs) ...@@ -920,6 +920,7 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data, struct pt_regs *regs)
{ {
struct controller *ctrl = data; struct controller *ctrl = data;
u8 schedule_flag = 0; u8 schedule_flag = 0;
u8 reset;
u16 misc; u16 misc;
u32 Diff; u32 Diff;
u32 temp_dword; u32 temp_dword;
...@@ -971,6 +972,15 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data, struct pt_regs *regs) ...@@ -971,6 +972,15 @@ irqreturn_t cpqhp_ctrl_intr(int IRQ, void *data, struct pt_regs *regs)
schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl); schedule_flag += handle_power_fault((u8)((Diff & 0xFF00L) >> 8), ctrl);
} }
reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
if (reset & 0x40) {
/* Bus reset has completed */
reset &= 0xCF;
writeb(reset, ctrl->hpc_reg + RESET_FREQ_MODE);
reset = readb(ctrl->hpc_reg + RESET_FREQ_MODE);
wake_up_interruptible(&ctrl->queue);
}
if (schedule_flag) { if (schedule_flag) {
up(&event_semaphore); up(&event_semaphore);
dbg("Signal event_semaphore\n"); dbg("Signal event_semaphore\n");
...@@ -1172,6 +1182,7 @@ static u32 board_replaced(struct pci_func * func, struct controller * ctrl) ...@@ -1172,6 +1182,7 @@ static u32 board_replaced(struct pci_func * func, struct controller * ctrl)
{ {
u8 hp_slot; u8 hp_slot;
u8 temp_byte; u8 temp_byte;
u8 adapter_speed;
u32 index; u32 index;
u32 rc = 0; u32 rc = 0;
u32 src = 8; u32 src = 8;
...@@ -1189,46 +1200,46 @@ static u32 board_replaced(struct pci_func * func, struct controller * ctrl) ...@@ -1189,46 +1200,46 @@ static u32 board_replaced(struct pci_func * func, struct controller * ctrl)
//********************************* //*********************************
rc = CARD_FUNCTIONING; rc = CARD_FUNCTIONING;
} else { } else {
if (ctrl->speed == PCI_SPEED_66MHz) { // Wait for exclusive access to hardware
// Wait for exclusive access to hardware down(&ctrl->crit_sect);
down(&ctrl->crit_sect);
// turn on board without attaching to the bus
enable_slot_power (ctrl, hp_slot);
set_SOGO(ctrl); // turn on board without attaching to the bus
enable_slot_power (ctrl, hp_slot);
// Wait for SOBS to be unset set_SOGO(ctrl);
wait_for_ctrl_irq (ctrl);
// Change bits in slot power register to force another shift out // Wait for SOBS to be unset
// NOTE: this is to work around the timer bug wait_for_ctrl_irq (ctrl);
temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
set_SOGO(ctrl); // Change bits in slot power register to force another shift out
// NOTE: this is to work around the timer bug
temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
// Wait for SOBS to be unset set_SOGO(ctrl);
wait_for_ctrl_irq (ctrl);
if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { // Wait for SOBS to be unset
wait_for_ctrl_irq (ctrl);
adapter_speed = get_adapter_speed(ctrl, hp_slot);
if (ctrl->speed != adapter_speed)
if (set_controller_speed(ctrl, adapter_speed, hp_slot))
rc = WRONG_BUS_FREQUENCY; rc = WRONG_BUS_FREQUENCY;
}
// turn off board without attaching to the bus
disable_slot_power (ctrl, hp_slot);
set_SOGO(ctrl); // turn off board without attaching to the bus
disable_slot_power (ctrl, hp_slot);
// Wait for SOBS to be unset set_SOGO(ctrl);
wait_for_ctrl_irq (ctrl);
// Done with exclusive hardware access // Wait for SOBS to be unset
up(&ctrl->crit_sect); wait_for_ctrl_irq (ctrl);
if (rc) // Done with exclusive hardware access
return(rc); up(&ctrl->crit_sect);
}
if (rc)
return(rc);
// Wait for exclusive access to hardware // Wait for exclusive access to hardware
down(&ctrl->crit_sect); down(&ctrl->crit_sect);
...@@ -1376,6 +1387,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) ...@@ -1376,6 +1387,7 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
{ {
u8 hp_slot; u8 hp_slot;
u8 temp_byte; u8 temp_byte;
u8 adapter_speed;
int index; int index;
u32 temp_register = 0xFFFFFFFF; u32 temp_register = 0xFFFFFFFF;
u32 rc = 0; u32 rc = 0;
...@@ -1387,47 +1399,48 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl) ...@@ -1387,47 +1399,48 @@ static u32 board_added(struct pci_func * func, struct controller * ctrl)
dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n", dbg("%s: func->device, slot_offset, hp_slot = %d, %d ,%d\n",
__FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot); __FUNCTION__, func->device, ctrl->slot_device_offset, hp_slot);
if (ctrl->speed == PCI_SPEED_66MHz) { // Wait for exclusive access to hardware
// Wait for exclusive access to hardware down(&ctrl->crit_sect);
down(&ctrl->crit_sect);
// turn on board without attaching to the bus
enable_slot_power (ctrl, hp_slot);
set_SOGO(ctrl); // turn on board without attaching to the bus
enable_slot_power (ctrl, hp_slot);
// Wait for SOBS to be unset set_SOGO(ctrl);
wait_for_ctrl_irq (ctrl);
// Change bits in slot power register to force another shift out // Wait for SOBS to be unset
// NOTE: this is to work around the timer bug wait_for_ctrl_irq (ctrl);
temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
set_SOGO(ctrl); // Change bits in slot power register to force another shift out
// NOTE: this is to work around the timer bug
temp_byte = readb(ctrl->hpc_reg + SLOT_POWER);
writeb(0x00, ctrl->hpc_reg + SLOT_POWER);
writeb(temp_byte, ctrl->hpc_reg + SLOT_POWER);
// Wait for SOBS to be unset set_SOGO(ctrl);
wait_for_ctrl_irq (ctrl);
if (!(readl(ctrl->hpc_reg + NON_INT_INPUT) & (0x01 << hp_slot))) { // Wait for SOBS to be unset
wait_for_ctrl_irq (ctrl);
adapter_speed = get_adapter_speed(ctrl, hp_slot);
if (ctrl->speed != adapter_speed)
if (set_controller_speed(ctrl, adapter_speed, hp_slot))
rc = WRONG_BUS_FREQUENCY; rc = WRONG_BUS_FREQUENCY;
}
// turn off board without attaching to the bus // turn off board without attaching to the bus
disable_slot_power (ctrl, hp_slot); disable_slot_power (ctrl, hp_slot);
set_SOGO(ctrl); set_SOGO(ctrl);
// Wait for SOBS to be unset // Wait for SOBS to be unset
wait_for_ctrl_irq (ctrl); wait_for_ctrl_irq (ctrl);
// Done with exclusive hardware access // Done with exclusive hardware access
up(&ctrl->crit_sect); up(&ctrl->crit_sect);
if (rc) if (rc)
return(rc); return(rc);
}
p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
// turn on board and blink green LED // turn on board and blink green LED
...@@ -1800,7 +1813,7 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -1800,7 +1813,7 @@ static void interrupt_event_handler(struct controller *ctrl)
if (!func) if (!func)
return; return;
p_slot = find_slot(ctrl, hp_slot + ctrl->slot_device_offset); p_slot = cpqhp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);
if (!p_slot) if (!p_slot)
return; return;
...@@ -1860,11 +1873,12 @@ static void interrupt_event_handler(struct controller *ctrl) ...@@ -1860,11 +1873,12 @@ static void interrupt_event_handler(struct controller *ctrl)
} }
// Wait for exclusive access to hardware // Wait for exclusive access to hardware
down(&ctrl->crit_sect); down(&ctrl->crit_sect);
dbg("blink green LED and turn off amber\n"); dbg("blink green LED and turn off amber\n");
amber_LED_off (ctrl, hp_slot); amber_LED_off (ctrl, hp_slot);
green_LED_blink (ctrl, hp_slot); green_LED_blink (ctrl, hp_slot);
set_SOGO(ctrl); set_SOGO(ctrl);
// Wait for SOBS to be unset // Wait for SOBS to be unset
...@@ -1992,7 +2006,7 @@ int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func) ...@@ -1992,7 +2006,7 @@ int cpqhp_process_SI (struct controller *ctrl, struct pci_func *func)
device = func->device; device = func->device;
hp_slot = device - ctrl->slot_device_offset; hp_slot = device - ctrl->slot_device_offset;
p_slot = find_slot(ctrl, device); p_slot = cpqhp_find_slot(ctrl, device);
if (p_slot) { if (p_slot) {
physical_slot = p_slot->number; physical_slot = p_slot->number;
} }
...@@ -2091,7 +2105,7 @@ int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func) ...@@ -2091,7 +2105,7 @@ int cpqhp_process_SS (struct controller *ctrl, struct pci_func *func)
device = func->device; device = func->device;
func = cpqhp_slot_find(ctrl->bus, device, index++); func = cpqhp_slot_find(ctrl->bus, device, index++);
p_slot = find_slot(ctrl, device); p_slot = cpqhp_find_slot(ctrl, device);
if (p_slot) { if (p_slot) {
physical_slot = p_slot->number; physical_slot = p_slot->number;
} }
......
...@@ -85,18 +85,20 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) ...@@ -85,18 +85,20 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
{ {
unsigned char bus; unsigned char bus;
struct pci_bus *child; struct pci_bus *child;
int rc = 0; int num;
if (func->pci_dev == NULL) if (func->pci_dev == NULL)
func->pci_dev = pci_find_slot(func->bus, (func->device << 3) | (func->function & 0x7)); func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
//Still NULL ? Well then scan for it ! /* No pci device, we need to create it then */
if (func->pci_dev == NULL) { if (func->pci_dev == NULL) {
dbg("INFO: pci_dev still null\n"); dbg("INFO: pci_dev still null\n");
//this will generate pci_dev structures for all functions, but we will only call this case when lookup fails num = pci_scan_slot(ctrl->pci_dev->bus, PCI_DEVFN(func->device, func->function));
func->pci_dev = pci_scan_slot(ctrl->pci_dev->bus, if (num)
(func->device << 3) + (func->function & 0x7)); pci_bus_add_devices(ctrl->pci_dev->bus);
func->pci_dev = pci_find_slot(func->bus, PCI_DEVFN(func->device, func->function));
if (func->pci_dev == NULL) { if (func->pci_dev == NULL) {
dbg("ERROR: pci_dev still null\n"); dbg("ERROR: pci_dev still null\n");
return 0; return 0;
...@@ -107,10 +109,9 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) ...@@ -107,10 +109,9 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus);
child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus);
pci_do_scan_bus(child); pci_do_scan_bus(child);
} }
return rc; return 0;
} }
...@@ -1209,11 +1210,11 @@ int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start) ...@@ -1209,11 +1210,11 @@ int cpqhp_find_available_resources (struct controller *ctrl, void *rom_start)
temp = 0; temp = 0;
if (!cpqhp_nic_irq) { if (!cpqhp_nic_irq) {
cpqhp_nic_irq = ctrl->interrupt; cpqhp_nic_irq = ctrl->cfgspc_irq;
} }
if (!cpqhp_disk_irq) { if (!cpqhp_disk_irq) {
cpqhp_disk_irq = ctrl->interrupt; cpqhp_disk_irq = ctrl->cfgspc_irq;
} }
dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq); dbg("cpqhp_disk_irq, cpqhp_nic_irq= %d, %d\n", cpqhp_disk_irq, cpqhp_nic_irq);
......
...@@ -846,22 +846,24 @@ static int ibm_configure_device (struct pci_func *func) ...@@ -846,22 +846,24 @@ static int ibm_configure_device (struct pci_func *func)
{ {
unsigned char bus; unsigned char bus;
struct pci_bus *child; struct pci_bus *child;
int rc = 0; int num;
int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */ int flag = 0; /* this is to make sure we don't double scan the bus, for bridged devices primarily */
if (!(bus_structure_fixup (func->busno))) if (!(bus_structure_fixup (func->busno)))
flag = 1; flag = 1;
if (func->dev == NULL) if (func->dev == NULL)
func->dev = pci_find_slot (func->busno, (func->device << 3) | (func->function & 0x7)); func->dev = pci_find_slot (func->busno, PCI_DEVFN(func->device, func->function));
if (func->dev == NULL) { if (func->dev == NULL) {
struct pci_bus *bus = ibmphp_find_bus (func->busno); struct pci_bus *bus = ibmphp_find_bus (func->busno);
if (!bus) if (!bus)
return 0; return 0;
func->dev = pci_scan_slot(bus, num = pci_scan_slot(bus, PCI_DEVFN(func->device, func->function));
(func->device << 3) + (func->function & 0x7)); if (num)
pci_bus_add_devices(bus);
func->dev = pci_find_slot(func->busno, PCI_DEVFN(func->device, func->function));
if (func->dev == NULL) { if (func->dev == NULL) {
err ("ERROR... : pci_dev still NULL \n"); err ("ERROR... : pci_dev still NULL \n");
return 0; return 0;
...@@ -873,7 +875,7 @@ static int ibm_configure_device (struct pci_func *func) ...@@ -873,7 +875,7 @@ static int ibm_configure_device (struct pci_func *func)
pci_do_scan_bus (child); pci_do_scan_bus (child);
} }
return rc; return 0;
} }
/******************************************************* /*******************************************************
...@@ -1415,7 +1417,7 @@ static int __init ibmphp_init (void) ...@@ -1415,7 +1417,7 @@ static int __init ibmphp_init (void)
/* lock ourselves into memory with a module /* lock ourselves into memory with a module
* count of -1 so that no one can unload us. */ * count of -1 so that no one can unload us. */
MOD_DEC_USE_COUNT; module_put(THIS_MODULE);
exit: exit:
return rc; return rc;
......
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