Commit ef7f120a authored by Irene Zubarev's avatar Irene Zubarev Committed by Greg Kroah-Hartman

[PATCH] IBM PCI Hotplug driver update for PCI based controllers

parent 9adaeddf
......@@ -737,6 +737,7 @@ struct slot {
struct controller {
struct ebda_hpc_slot *slots;
struct ebda_hpc_bus *buses;
struct pci_dev *ctrl_dev; /* in case where controller is PCI */
u8 starting_slot_num; /* starting and ending slot #'s this ctrl controls*/
u8 ending_slot_num;
u8 revision;
......
......@@ -1636,6 +1636,11 @@ static int __init ibmphp_init (void)
max_slots = get_max_slots ();
if ((rc = ibmphp_register_pci ())) {
ibmphp_unload ();
return rc;
}
if (init_ops ()) {
ibmphp_unload ();
return -ENODEV;
......
......@@ -131,6 +131,7 @@ static void free_ebda_hpc (struct controller *controller)
controller->slots = NULL;
kfree (controller->buses);
controller->buses = NULL;
controller->ctrl_dev = NULL;
kfree (controller);
}
......@@ -798,6 +799,8 @@ static char *create_file_name (struct slot * slot_cur)
return NULL;
}
static struct pci_driver ibmphp_driver;
/*
* map info (ctlr-id, slot count, slot#.. bus count, bus#, ctlr type...) of
* each hpc from physical address to a list of hot plug controllers based on
......@@ -929,6 +932,7 @@ static int __init ebda_rsrc_controller (void)
hpc_ptr->u.pci_ctlr.dev_fun = readb (io_mem + addr + 1);
hpc_ptr->irq = readb (io_mem + addr + 2);
addr += 3;
debug ("ctrl bus = %x, ctlr devfun = %x, irq = %x\n", hpc_ptr->u.pci_ctlr.bus, hpc_ptr->u.pci_ctlr.dev_fun, hpc_ptr->irq);
break;
case 0:
......@@ -954,12 +958,6 @@ static int __init ebda_rsrc_controller (void)
return -ENODEV;
}
/* following 3 line: Now our driver only supports I2c/ISA ctlrType */
if ((hpc_ptr->ctlr_type != 2) && (hpc_ptr->ctlr_type != 4) && (hpc_ptr->ctlr_type != 0)) {
err ("Please run this driver on IBM xSeries440 or xSeries 235\n ");
return -ENODEV;
}
//reorganize chassis' linked list
combine_wpg_for_chassis ();
combine_wpg_for_expansion ();
......@@ -1213,11 +1211,16 @@ void ibmphp_free_ebda_hpc_queue (void)
struct controller *controller = NULL;
struct list_head *list;
struct list_head *next;
int pci_flag = 0;
list_for_each_safe (list, next, &ebda_hpc_head) {
controller = list_entry (list, struct controller, ebda_hpc_list);
if (controller->ctlr_type == 0)
release_region (controller->u.isa_ctlr.io_start, (controller->u.isa_ctlr.io_end - controller->u.isa_ctlr.io_start + 1));
else if ((controller->ctlr_type == 1) && (!pci_flag)) {
++pci_flag;
pci_unregister_driver (&ibmphp_driver);
}
free_ebda_hpc (controller);
}
}
......@@ -1234,3 +1237,59 @@ void ibmphp_free_ebda_pci_rsrc_queue (void)
resource = NULL;
}
}
static struct pci_device_id id_table[] __devinitdata = {
{
vendor: PCI_VENDOR_ID_IBM,
device: HPC_DEVICE_ID,
subvendor: PCI_VENDOR_ID_IBM,
subdevice: HPC_SUBSYSTEM_ID,
class: ((PCI_CLASS_SYSTEM_PCI_HOTPLUG << 8) | 0x00),
}, {}
};
MODULE_DEVICE_TABLE(pci, id_table);
static int ibmphp_probe (struct pci_dev *, const struct pci_device_id *);
static struct pci_driver ibmphp_driver = {
name: "ibmphp",
id_table: id_table,
probe: ibmphp_probe,
};
int ibmphp_register_pci (void)
{
struct controller *ctrl;
struct list_head *tmp;
int rc = 0;
list_for_each (tmp, &ebda_hpc_head) {
ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
if (ctrl->ctlr_type == 1) {
rc = pci_module_init (&ibmphp_driver);
break;
}
}
return rc;
}
static int ibmphp_probe (struct pci_dev * dev, const struct pci_device_id *ids)
{
struct controller *ctrl;
struct list_head *tmp;
debug ("inside ibmphp_probe \n");
list_for_each (tmp, &ebda_hpc_head) {
ctrl = list_entry (tmp, struct controller, ebda_hpc_list);
if (ctrl->ctlr_type == 1) {
if ((dev->devfn == ctrl->u.pci_ctlr.dev_fun) && (dev->bus->number == ctrl->u.pci_ctlr.bus)) {
ctrl->ctrl_dev = dev;
debug ("found device!!! \n");
debug ("dev->device = %x, dev->subsystem_device = %x\n", dev->device, dev->subsystem_device);
return 0;
}
}
}
return -ENODEV;
}
......@@ -379,6 +379,26 @@ static void isa_ctrl_write (struct controller *ctlr_ptr, u8 offset, u8 data)
outb (data, port_address);
}
static u8 pci_ctrl_read (struct controller *ctrl, u8 offset)
{
u8 data = 0x00;
debug ("inside pci_ctrl_read\n");
if (ctrl->ctrl_dev)
pci_read_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, &data);
return data;
}
static u8 pci_ctrl_write (struct controller *ctrl, u8 offset, u8 data)
{
u8 rc = -ENODEV;
debug ("inside pci_ctrl_write\n");
if (ctrl->ctrl_dev) {
pci_write_config_byte (ctrl->ctrl_dev, HPC_PCI_OFFSET + offset, data);
rc = 0;
}
return rc;
}
static u8 ctrl_read (struct controller *ctlr, void *base, u8 offset)
{
u8 rc;
......@@ -386,6 +406,9 @@ static u8 ctrl_read (struct controller *ctlr, void *base, u8 offset)
case 0:
rc = isa_ctrl_read (ctlr, offset);
break;
case 1:
rc = pci_ctrl_read (ctlr, offset);
break;
case 2:
case 4:
rc = i2c_ctrl_read (ctlr, base, offset);
......@@ -403,6 +426,9 @@ static u8 ctrl_write (struct controller *ctlr, void *base, u8 offset, u8 data)
case 0:
isa_ctrl_write(ctlr, offset, data);
break;
case 1:
rc = pci_ctrl_write (ctlr, offset, data);
break;
case 2:
case 4:
rc = i2c_ctrl_write(ctlr, base, offset, data);
......
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