[PATCH 6/8] PCI/hotplug/rpa: Abstract slot operations

Gavin Shan gwshan at linux.vnet.ibm.com
Wed Nov 26 11:01:15 AEDT 2014


On Wed, Nov 26, 2014 at 10:04:36AM +1100, Benjamin Herrenschmidt wrote:
>On Tue, 2014-11-25 at 09:49 +1100, Gavin Shan wrote:
>> The patch splits the code into 2 parts: RPA PCI hotplug slot
>> management and RTAS backend. It enables us to support PowerNV,
>> which is built on top of OPAL firmware in future.
>> 
>> The patch also refactors the code for a bit:
>> 
>>     * Rename "struct slot" to "struct rpa_php_slot"
>>     * All macros have prefix "RPA_PHP_SLOT"
>>     * rpaphp_slot.c is removed and all logics moved to rpaphp_core.c
>
>
>I don't see the point of this. rpaphp is already itself a "backend", so
>we end up with yet another layer.
>

Yes, that's what I did.

>Just create a powernv-php or opal-php and if there is common code,
>factor it into a common helper but I wouldn't bother too much initially
>unless there is a lot of it.
>

Ok. I'll create powernv-php.

Thanks,
Gavin

>> Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
>> ---
>>  drivers/pci/hotplug/Makefile        |   3 +-
>>  drivers/pci/hotplug/rpadlpar_core.c |  10 +-
>>  drivers/pci/hotplug/rpaphp.h        |  64 +++----
>>  drivers/pci/hotplug/rpaphp_core.c   | 347 +++++++++++-------------------------
>>  drivers/pci/hotplug/rpaphp_pci.c    | 136 --------------
>>  drivers/pci/hotplug/rpaphp_rtas.c   | 320 +++++++++++++++++++++++++++++++++
>>  drivers/pci/hotplug/rpaphp_slot.c   | 140 ---------------
>>  7 files changed, 459 insertions(+), 561 deletions(-)
>>  delete mode 100644 drivers/pci/hotplug/rpaphp_pci.c
>>  create mode 100644 drivers/pci/hotplug/rpaphp_rtas.c
>>  delete mode 100644 drivers/pci/hotplug/rpaphp_slot.c
>> 
>> diff --git a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
>> index 4a9aa08..630313da 100644
>> --- a/drivers/pci/hotplug/Makefile
>> +++ b/drivers/pci/hotplug/Makefile
>> @@ -51,8 +51,7 @@ acpiphp-objs		:=	acpiphp_core.o	\
>>  				acpiphp_glue.o
>>  
>>  rpaphp-objs		:=	rpaphp_core.o	\
>> -				rpaphp_pci.o	\
>> -				rpaphp_slot.o
>> +				rpaphp_rtas.o
>>  
>>  rpadlpar_io-objs	:=	rpadlpar_core.o \
>>  				rpadlpar_sysfs.o
>> diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c
>> index 35da3b3..a36d2c9 100644
>> --- a/drivers/pci/hotplug/rpadlpar_core.c
>> +++ b/drivers/pci/hotplug/rpadlpar_core.c
>> @@ -117,13 +117,13 @@ static struct device_node *find_dlpar_node(char *drc_name, int *node_type)
>>   * may be dlpar-able, but not hot-pluggable, so this routine
>>   * will return NULL for built-in PCI slots.
>>   */
>> -static struct slot *find_php_slot(struct device_node *dn)
>> +static struct rpa_php_slot *find_php_slot(struct device_node *dn)
>>  {
>>  	struct list_head *tmp, *n;
>> -	struct slot *slot;
>> +	struct rpa_php_slot *slot;
>>  
>>  	list_for_each_safe(tmp, n, &rpaphp_slot_head) {
>> -		slot = list_entry(tmp, struct slot, rpaphp_slot_list);
>> +		slot = list_entry(tmp, struct rpa_php_slot, rpaphp_slot_list);
>>  		if (slot->dn == dn)
>>  			return slot;
>>  	}
>> @@ -214,7 +214,7 @@ static int dlpar_add_pci_slot(char *drc_name, struct device_node *dn)
>>  
>>  static int dlpar_remove_phb(char *drc_name, struct device_node *dn)
>>  {
>> -	struct slot *slot;
>> +	struct rpa_php_slot *slot;
>>  	struct pci_dn *pdn;
>>  	int rc = 0;
>>  
>> @@ -359,7 +359,7 @@ static int dlpar_remove_vio_slot(char *drc_name, struct device_node *dn)
>>  int dlpar_remove_pci_slot(char *drc_name, struct device_node *dn)
>>  {
>>  	struct pci_bus *bus;
>> -	struct slot *slot;
>> +	struct rpa_php_slot *slot;
>>  	int ret = 0;
>>  
>>  	pci_lock_rescan_remove();
>> diff --git a/drivers/pci/hotplug/rpaphp.h b/drivers/pci/hotplug/rpaphp.h
>> index 39ddbdf..09dd516 100644
>> --- a/drivers/pci/hotplug/rpaphp.h
>> +++ b/drivers/pci/hotplug/rpaphp.h
>> @@ -30,21 +30,6 @@
>>  #include <linux/pci.h>
>>  #include <linux/pci_hotplug.h>
>>  
>> -#define DR_INDICATOR 9002
>> -#define DR_ENTITY_SENSE 9003
>> -
>> -#define POWER_ON	100
>> -#define POWER_OFF	0
>> -
>> -#define LED_OFF		0
>> -#define LED_ON		1	/* continuous on */
>> -#define LED_ID		2	/* slow blinking */
>> -#define LED_ACTION	3	/* fast blinking */
>> -
>> -/* Sensor values from rtas_get-sensor */
>> -#define EMPTY           0	/* No card in slot */
>> -#define PRESENT         1	/* Card in slot */
>> -
>>  #define MY_NAME "rpaphp"
>>  extern bool rpaphp_debug;
>>  #define dbg(format, arg...)					\
>> @@ -57,19 +42,26 @@ extern bool rpaphp_debug;
>>  #define info(format, arg...) printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
>>  #define warn(format, arg...) printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
>>  
>> -/* slot states */
>> +/* Power */
>> +#define RPA_PHP_SLOT_POWER_ON	1	/* On            */
>> +#define RPA_PHP_SLOT_POWER_OFF	0	/* Off           */
>>  
>> -#define	NOT_VALID	3
>> -#define	NOT_CONFIGURED	2
>> -#define	CONFIGURED	1
>> -#define	EMPTY		0
>> +/* Attention */
>> +#define RPA_PHP_SLOT_ATTEN_OFF	0	/* Off           */
>> +#define RPA_PHP_SLOT_ATTEN_ON	1	/* On            */
>> +#define RPA_PHP_SLOT_ATTEN_IND	2	/* Slow blinking */
>> +#define RPA_PHP_SLOT_ATTEN_ACT	3	/* Fast blinking */
>>  
>> -/*
>> - * struct slot - slot information for each *physical* slot
>> - */
>> -struct slot {
>> +/* Presence */
>> +#define RPA_PHP_SLOT_EMPTY	0	/* No card       */
>> +#define RPA_PHP_SLOT_PRESENT	1	/* Presented     */
>> +
>> +struct rpa_php_slot {
>>  	struct list_head rpaphp_slot_list;
>>  	int state;
>> +#define RPA_PHP_SLOT_NOT_CONFIGURED	0
>> +#define RPA_PHP_SLOT_CONFIGURED		1
>> +#define RPA_PHP_SLOT_NOT_VALID		2
>>  	u32 index;
>>  	u32 type;
>>  	u32 power_domain;
>> @@ -80,24 +72,20 @@ struct slot {
>>  	struct hotplug_slot *hotplug_slot;
>>  };
>>  
>> -extern struct hotplug_slot_ops rpaphp_hotplug_slot_ops;
>>  extern struct list_head rpaphp_slot_head;
>>  
>> -/* function prototypes */
>> -
>> -/* rpaphp_pci.c */
>> -int rpaphp_enable_slot(struct slot *slot);
>> -int rpaphp_get_sensor_state(struct slot *slot, int *state);
>> -
>>  /* rpaphp_core.c */
>>  int rpaphp_add_slot(struct device_node *dn);
>> -int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
>> -		char **drc_name, char **drc_type, int *drc_power);
>> +void dealloc_slot_struct(struct rpa_php_slot *slot);
>> +struct rpa_php_slot *alloc_slot_struct(struct device_node *dn, int drc_index,
>> +				       char *drc_name, int power_domain);
>> +int rpaphp_register_slot(struct rpa_php_slot *slot);
>> +int rpaphp_deregister_slot(struct rpa_php_slot *slot);
>> +int rpaphp_add_slot(struct device_node *dn);
>>  
>> -/* rpaphp_slot.c */
>> -void dealloc_slot_struct(struct slot *slot);
>> -struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name, int power_domain);
>> -int rpaphp_register_slot(struct slot *slot);
>> -int rpaphp_deregister_slot(struct slot *slot);
>> +/* rpaphp_rtas.c */
>> +int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
>> +			 char **drc_name, char **drc_type, int *drc_power);
>> +struct rpa_php_slot *rpaphp_rtas_add_slot(struct device_node *dn);
>>  
>>  #endif				/* _PPC64PHP_H */
>> diff --git a/drivers/pci/hotplug/rpaphp_core.c b/drivers/pci/hotplug/rpaphp_core.c
>> index a639c5c..91eff8f 100644
>> --- a/drivers/pci/hotplug/rpaphp_core.c
>> +++ b/drivers/pci/hotplug/rpaphp_core.c
>> @@ -45,194 +45,118 @@ EXPORT_SYMBOL_GPL(rpaphp_slot_head);
>>  #define DRIVER_AUTHOR	"Linda Xie <lxie at us.ibm.com>"
>>  #define DRIVER_DESC	"RPA HOT Plug PCI Controller Driver"
>>  
>> -#define MAX_LOC_CODE 128
>> -
>> -MODULE_AUTHOR(DRIVER_AUTHOR);
>> -MODULE_DESCRIPTION(DRIVER_DESC);
>> -MODULE_LICENSE("GPL");
>> -
>>  module_param_named(debug, rpaphp_debug, bool, 0644);
>>  
>> -/**
>> - * set_attention_status - set attention LED
>> - * @hotplug_slot: target &hotplug_slot
>> - * @value: LED control value
>> - *
>> - * echo 0 > attention -- set LED OFF
>> - * echo 1 > attention -- set LED ON
>> - * echo 2 > attention -- set LED ID(identify, light is blinking)
>> - */
>> -static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value)
>> +/* free up the memory used by a slot */
>> +static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
>>  {
>> -	int rc;
>> -	struct slot *slot = (struct slot *)hotplug_slot->private;
>> -
>> -	switch (value) {
>> -	case 0:
>> -	case 1:
>> -	case 2:
>> -		break;
>> -	default:
>> -		value = 1;
>> -	}
>> +	struct rpa_php_slot *slot = hotplug_slot->private;
>>  
>> -	rc = rtas_set_indicator(DR_INDICATOR, slot->index, value);
>> -	if (!rc)
>> -		hotplug_slot->info->attention_status = value;
>> -
>> -	return rc;
>> +	dealloc_slot_struct(slot);
>>  }
>>  
>> -/**
>> - * get_power_status - get power status of a slot
>> - * @hotplug_slot: slot to get status
>> - * @value: pointer to store status
>> - */
>> -static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
>> +void dealloc_slot_struct(struct rpa_php_slot *slot)
>>  {
>> -	int retval, level;
>> -	struct slot *slot = (struct slot *)hotplug_slot->private;
>> -
>> -	retval = rtas_get_power_level(slot->power_domain, &level);
>> -	if (!retval)
>> -		*value = level;
>> -	return retval;
>> +	kfree(slot->hotplug_slot->info);
>> +	kfree(slot->name);
>> +	kfree(slot->hotplug_slot);
>> +	kfree(slot);
>>  }
>>  
>> -/**
>> - * get_attention_status - get attention LED status
>> - * @hotplug_slot: slot to get status
>> - * @value: pointer to store status
>> - */
>> -static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
>> +struct rpa_php_slot *alloc_slot_struct(struct device_node *dn,
>> +				       int drc_index, char *drc_name,
>> +				       int power_domain)
>>  {
>> -	struct slot *slot = (struct slot *)hotplug_slot->private;
>> -	*value = slot->hotplug_slot->info->attention_status;
>> -	return 0;
>> -}
>> -
>> -static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
>> -{
>> -	struct slot *slot = (struct slot *)hotplug_slot->private;
>> -	int rc, state;
>> -
>> -	rc = rpaphp_get_sensor_state(slot, &state);
>> -
>> -	*value = NOT_VALID;
>> -	if (rc)
>> -		return rc;
>> +	struct rpa_php_slot *slot;
>>  
>> -	if (state == EMPTY)
>> -		*value = EMPTY;
>> -	else if (state == PRESENT)
>> -		*value = slot->state;
>> -
>> -	return 0;
>> +	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
>> +	if (!slot)
>> +		goto error_nomem;
>> +	slot->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
>> +	if (!slot->hotplug_slot)
>> +		goto error_slot;
>> +	slot->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
>> +					   GFP_KERNEL);
>> +	if (!slot->hotplug_slot->info)
>> +		goto error_hpslot;
>> +	slot->name = kstrdup(drc_name, GFP_KERNEL);
>> +	if (!slot->name)
>> +		goto error_info;
>> +	slot->dn = dn;
>> +	slot->index = drc_index;
>> +	slot->power_domain = power_domain;
>> +	slot->hotplug_slot->private = slot;
>> +	slot->hotplug_slot->release = &rpaphp_release_slot;
>> +
>> +	slot->hotplug_slot->info->power_status = RPA_PHP_SLOT_POWER_ON;
>> +	slot->hotplug_slot->info->attention_status = RPA_PHP_SLOT_ATTEN_OFF;
>> +	slot->hotplug_slot->info->adapter_status = RPA_PHP_SLOT_EMPTY;
>> +	slot->state = RPA_PHP_SLOT_NOT_VALID;
>> +
>> +	return slot;
>> +
>> +error_info:
>> +	kfree(slot->hotplug_slot->info);
>> +error_hpslot:
>> +	kfree(slot->hotplug_slot);
>> +error_slot:
>> +	kfree(slot);
>> +error_nomem:
>> +	return NULL;
>>  }
>>  
>> -static enum pci_bus_speed get_max_bus_speed(struct slot *slot)
>> +int rpaphp_register_slot(struct rpa_php_slot *slot)
>>  {
>> -	enum pci_bus_speed speed;
>> -	switch (slot->type) {
>> -	case 1:
>> -	case 2:
>> -	case 3:
>> -	case 4:
>> -	case 5:
>> -	case 6:
>> -		speed = PCI_SPEED_33MHz;	/* speed for case 1-6 */
>> -		break;
>> -	case 7:
>> -	case 8:
>> -		speed = PCI_SPEED_66MHz;
>> -		break;
>> -	case 11:
>> -	case 14:
>> -		speed = PCI_SPEED_66MHz_PCIX;
>> -		break;
>> -	case 12:
>> -	case 15:
>> -		speed = PCI_SPEED_100MHz_PCIX;
>> -		break;
>> -	case 13:
>> -	case 16:
>> -		speed = PCI_SPEED_133MHz_PCIX;
>> -		break;
>> -	default:
>> -		speed = PCI_SPEED_UNKNOWN;
>> +	struct hotplug_slot *php_slot = slot->hotplug_slot;
>> +	struct rpa_php_slot *tmp;
>> +	int slotno, retval;
>> +
>> +	dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",
>> +	    __func__, slot->dn->full_name, slot->index, slot->name,
>> +	    slot->power_domain, slot->type);
>> +
>> +	/* Should not try to register the same slot twice */
>> +	list_for_each_entry(tmp, &rpaphp_slot_head, rpaphp_slot_list) {
>> +		if (!strcmp(tmp->name, slot->name)) {
>> +			err("%s: Slot[%s] is already registered\n",
>> +			    __func__, slot->name);
>> +			return -EAGAIN;
>> +		}
>> +	}
>> +	if (slot->dn->child)
>> +		slotno = PCI_SLOT(PCI_DN(slot->dn->child)->devfn);
>> +	else
>> +		slotno = -1;
>> +	retval = pci_hp_register(php_slot, slot->bus, slotno, slot->name);
>> +	if (retval) {
>> +		err("pci_hp_register failed with error %d\n", retval);
>> +		return retval;
>>  	}
>>  
>> -	return speed;
>> +	/* add slot to our internal list */
>> +	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
>> +	info("Slot [%s] registered\n", slot->name);
>> +	return 0;
>>  }
>>  
>> -static int parse_drc_props(struct device_node *dn, u32 drc_index,
>> -			   char **drc_name, char **drc_type, u32 *drc_power)
>> +int rpaphp_deregister_slot(struct rpa_php_slot *slot)
>>  {
>> -	const u32 *indexes, *names, *types, *domains;
>> -	char *name, *type;
>> -	struct device_node *parent = dn;
>> -	u32 i;
>> -
>> -	while ((parent = of_get_parent(parent))) {
>> -		indexes = of_get_property(parent, "ibm,drc-indexes", NULL);
>> -		names   = of_get_property(parent, "ibm,drc-names", NULL);
>> -		types   = of_get_property(parent, "ibm,drc-types", NULL);
>> -		domains = of_get_property(parent, "ibm,drc-power-domains", NULL);
>> -
>> -		if (!indexes || !names || !types || !domains) {
>> -			of_node_put(parent);
>> -			continue;
>> -		}
>> +	struct hotplug_slot *php_slot = slot->hotplug_slot;
>> +	int retval = 0;
>>  
>> -		name = (char *)&names[1];
>> -		type = (char *)&types[1];
>> -		for (i = 0; i < be32_to_cpu(indexes[0]); i++) {
>> -			if (be32_to_cpu(indexes[i + 1]) != drc_index) {
>> -				name += (strlen(name) + 1);
>> -				type += (strlen(type) + 1);
>> -				continue;
>> -			}
>> -
>> -			/* Matched index */
>> -			if (drc_name)
>> -				*drc_name = name;
>> -			if (drc_type)
>> -				*drc_type = type;
>> -			if (drc_power)
>> -				*drc_power = be32_to_cpu(domains[i + 1]);
>> -
>> -			of_node_put(parent);
>> -			return 0;
>> -		}
>> -
>> -		/* Next level parent */
>> -		of_node_put(parent);
>> -	}
>> +	dbg("%s - Entry: deregistering slot=%s\n",
>> +	    __func__, slot->name);
>>  
>> -	return -ENODEV;
>> -}
>> +	list_del(&slot->rpaphp_slot_list);
>>  
>> -/*
>> - * To get the DRC props describing the current node, first obtain it's
>> - * my-drc-index property.  Next obtain the DRC list from it's parent.  Use
>> - * the my-drc-index for correlation, and obtain the requested properties.
>> - */
>> -int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
>> -			 char **drc_name, char **drc_type, int *drc_power)
>> -{
>> -	const u32 *my_index;
>> -
>> -	/* Check if node is capable of hotplug */
>> -	my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
>> -	if (!my_index)
>> -		return -EINVAL;
>> -	if (drc_index)
>> -		*drc_index = be32_to_cpu(*my_index);
>> +	retval = pci_hp_deregister(php_slot);
>> +	if (retval)
>> +		err("Problem unregistering a slot %s\n", slot->name);
>>  
>> -	return parse_drc_props(dn, be32_to_cpu(*my_index),
>> -			       drc_name, drc_type, drc_power);
>> +	dbg("%s - Exit: rc[%d]\n", __func__, retval);
>> +	return retval;
>>  }
>> -EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
>> +EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
>>  
>>  /**
>>   * rpaphp_add_slot -- declare a hotplug slot to the hotplug subsystem.
>> @@ -252,29 +176,22 @@ EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
>>   */
>>  int rpaphp_add_slot(struct device_node *dn)
>>  {
>> -	char *name, *type, *endptr;
>> -	int index, power_domain;
>> -	struct slot *slot;
>> -	int val, ret;
>> -
>> -	/* Get and parse the hotplug properties */
>> -	ret = rpaphp_get_drc_props(dn, &index, &name, &type, &power_domain);
>> -	if (ret)
>> -		return ret;
>> -
>> -	/* PCI Hotplug nodes have an integer for drc_type */
>> -	val = simple_strtoul(type, &endptr, 10);
>> -	if (endptr == type)
>> -		return -EINVAL;
>> +	struct rpa_php_slot *slot = NULL;
>> +	int ret;
>>  
>> -	slot = alloc_slot_struct(dn, index, name, power_domain);
>> +	/* Create slot */
>> +	if (machine_is(pseries))
>> +		slot = rpaphp_rtas_add_slot(dn);
>>  	if (!slot)
>> -		return -ENOMEM;
>> +		return -EIO;
>>  
>> -	slot->type = val;
>> -	ret = rpaphp_enable_slot(slot);
>> -	if (!ret)
>> -		ret = rpaphp_register_slot(slot);
>> +	/* Enable slot */
>> +	ret = slot->hotplug_slot->ops->enable_slot(slot->hotplug_slot);
>> +	if (ret)
>> +		goto fail;
>> +
>> +	/* Register slot */
>> +	ret = rpaphp_register_slot(slot);
>>  	if (ret)
>>  		goto fail;
>>  
>> @@ -288,7 +205,7 @@ EXPORT_SYMBOL_GPL(rpaphp_add_slot);
>>  static void __exit cleanup_slots(void)
>>  {
>>  	struct list_head *tmp, *n;
>> -	struct slot *slot;
>> +	struct rpa_php_slot *slot;
>>  
>>  	/*
>>  	 * Unregister all of our slots with the pci_hotplug subsystem,
>> @@ -297,7 +214,7 @@ static void __exit cleanup_slots(void)
>>  	 */
>>  
>>  	list_for_each_safe(tmp, n, &rpaphp_slot_head) {
>> -		slot = list_entry(tmp, struct slot, rpaphp_slot_list);
>> +		slot = list_entry(tmp, struct rpa_php_slot, rpaphp_slot_list);
>>  		list_del(&slot->rpaphp_slot_list);
>>  		pci_hp_deregister(slot->hotplug_slot);
>>  	}
>> @@ -320,59 +237,9 @@ static void __exit rpaphp_exit(void)
>>  	cleanup_slots();
>>  }
>>  
>> -static int enable_slot(struct hotplug_slot *hotplug_slot)
>> -{
>> -	struct slot *slot = (struct slot *)hotplug_slot->private;
>> -	int state;
>> -	int retval;
>> -
>> -	if (slot->state == CONFIGURED)
>> -		return 0;
>> -
>> -	retval = rpaphp_get_sensor_state(slot, &state);
>> -	if (retval)
>> -		return retval;
>> -
>> -	if (state == PRESENT) {
>> -		pci_lock_rescan_remove();
>> -		pcibios_add_pci_devices(slot->bus);
>> -		pci_unlock_rescan_remove();
>> -		slot->state = CONFIGURED;
>> -	} else if (state == EMPTY) {
>> -		slot->state = EMPTY;
>> -	} else {
>> -		err("%s: slot[%s] is in invalid state\n", __func__, slot->name);
>> -		slot->state = NOT_VALID;
>> -		return -EINVAL;
>> -	}
>> -
>> -	slot->bus->max_bus_speed = get_max_bus_speed(slot);
>> -	return 0;
>> -}
>> -
>> -static int disable_slot(struct hotplug_slot *hotplug_slot)
>> -{
>> -	struct slot *slot = (struct slot *)hotplug_slot->private;
>> -	if (slot->state == NOT_CONFIGURED)
>> -		return -EINVAL;
>> -
>> -	pci_lock_rescan_remove();
>> -	pcibios_remove_pci_devices(slot->bus);
>> -	pci_unlock_rescan_remove();
>> -	vm_unmap_aliases();
>> -
>> -	slot->state = NOT_CONFIGURED;
>> -	return 0;
>> -}
>> -
>> -struct hotplug_slot_ops rpaphp_hotplug_slot_ops = {
>> -	.enable_slot = enable_slot,
>> -	.disable_slot = disable_slot,
>> -	.set_attention_status = set_attention_status,
>> -	.get_power_status = get_power_status,
>> -	.get_attention_status = get_attention_status,
>> -	.get_adapter_status = get_adapter_status,
>> -};
>> -
>>  module_init(rpaphp_init);
>>  module_exit(rpaphp_exit);
>> +
>> +MODULE_AUTHOR(DRIVER_AUTHOR);
>> +MODULE_DESCRIPTION(DRIVER_DESC);
>> +MODULE_LICENSE("GPL");
>> diff --git a/drivers/pci/hotplug/rpaphp_pci.c b/drivers/pci/hotplug/rpaphp_pci.c
>> deleted file mode 100644
>> index a4aa65c..0000000
>> --- a/drivers/pci/hotplug/rpaphp_pci.c
>> +++ /dev/null
>> @@ -1,136 +0,0 @@
>> -/*
>> - * PCI Hot Plug Controller Driver for RPA-compliant PPC64 platform.
>> - * Copyright (C) 2003 Linda Xie <lxie at us.ibm.com>
>> - *
>> - * All rights reserved.
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License as published by
>> - * the Free Software Foundation; either version 2 of the License, or (at
>> - * your option) any later version.
>> - *
>> - * This program is distributed in the hope that it will be useful, but
>> - * WITHOUT ANY WARRANTY; without even the implied warranty of
>> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
>> - * NON INFRINGEMENT.  See the GNU General Public License for more
>> - * details.
>> - *
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program; if not, write to the Free Software
>> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
>> - *
>> - * Send feedback to <lxie at us.ibm.com>
>> - *
>> - */
>> -#include <linux/pci.h>
>> -#include <linux/string.h>
>> -
>> -#include <asm/pci-bridge.h>
>> -#include <asm/rtas.h>
>> -#include <asm/machdep.h>
>> -
>> -#include "../pci.h"		/* for pci_add_new_bus */
>> -#include "rpaphp.h"
>> -
>> -int rpaphp_get_sensor_state(struct slot *slot, int *state)
>> -{
>> -	int rc;
>> -	int setlevel;
>> -
>> -	rc = rtas_get_sensor(DR_ENTITY_SENSE, slot->index, state);
>> -	if (rc >= 0)
>> -		return rc;
>> -	if (rc != -EFAULT && rc != -EEXIST) {
>> -		err("%s: Failure %d getting sensor state on slot[%s]\n",
>> -		    __func__, rc, slot->name);
>> -		return rc;
>> -	}
>> -
>> -
>> -	/*
>> -	 * Some slots have to be powered up before
>> -	 * get-sensor will succeed
>> -	 */
>> -	dbg("%s: Slot[%s] must be power up to get sensor-state\n",
>> -	    __func__, slot->name);
>> -	rc = rtas_set_power_level(slot->power_domain, POWER_ON,
>> -				  &setlevel);
>> -	if (rc < 0) {
>> -		dbg("%s: Failure %d powerng on slot[%s]\n",
>> -		    __func__, rc, slot->name);
>> -		return rc;
>> -	}
>> -
>> -	return rtas_get_sensor(DR_ENTITY_SENSE,
>> -			       slot->index, state);
>> -}
>> -
>> -/**
>> - * rpaphp_enable_slot - record slot state, config pci device
>> - * @slot: target &slot
>> - *
>> - * Initialize values in the slot, and the hotplug_slot info
>> - * structures to indicate if there is a pci card plugged into
>> - * the slot. If the slot is not empty, run the pcibios routine
>> - * to get pcibios stuff correctly set up.
>> - */
>> -int rpaphp_enable_slot(struct slot *slot)
>> -{
>> -	int rc, level, state;
>> -	struct pci_bus *bus;
>> -	struct hotplug_slot_info *info = slot->hotplug_slot->info;
>> -
>> -	info->adapter_status = NOT_VALID;
>> -	slot->state = EMPTY;
>> -
>> -	/* Find out if the power is turned on for the slot */
>> -	rc = rtas_get_power_level(slot->power_domain, &level);
>> -	if (rc)
>> -		return rc;
>> -	info->power_status = level;
>> -
>> -	/* Figure out if there is an adapter in the slot */
>> -	rc = rpaphp_get_sensor_state(slot, &state);
>> -	if (rc)
>> -		return rc;
>> -
>> -	bus = pcibios_find_pci_bus(slot->dn);
>> -	if (!bus) {
>> -		err("%s: no pci_bus for dn %s\n", __func__, slot->dn->full_name);
>> -		return -EINVAL;
>> -	}
>> -
>> -	info->adapter_status = EMPTY;
>> -	slot->bus = bus;
>> -	slot->pci_devs = &bus->devices;
>> -
>> -	/* if there's an adapter in the slot, go add the pci devices */
>> -	if (state == PRESENT) {
>> -		info->adapter_status = NOT_CONFIGURED;
>> -		slot->state = NOT_CONFIGURED;
>> -
>> -		/* non-empty slot has to have child */
>> -		if (!slot->dn->child) {
>> -			err("%s: slot[%s]'s device_node doesn't have child for adapter\n",
>> -			    __func__, slot->name);
>> -			return -EINVAL;
>> -		}
>> -
>> -		if (list_empty(&bus->devices))
>> -			pcibios_add_pci_devices(bus);
>> -
>> -		if (!list_empty(&bus->devices)) {
>> -			info->adapter_status = CONFIGURED;
>> -			slot->state = CONFIGURED;
>> -		}
>> -
>> -		if (rpaphp_debug) {
>> -			struct pci_dev *dev;
>> -			dbg("%s: pci_devs of slot[%s]\n", __func__, slot->dn->full_name);
>> -			list_for_each_entry (dev, &bus->devices, bus_list)
>> -				dbg("\t%s\n", pci_name(dev));
>> -		}
>> -	}
>> -
>> -	return 0;
>> -}
>> diff --git a/drivers/pci/hotplug/rpaphp_rtas.c b/drivers/pci/hotplug/rpaphp_rtas.c
>> new file mode 100644
>> index 0000000..74f024a
>> --- /dev/null
>> +++ b/drivers/pci/hotplug/rpaphp_rtas.c
>> @@ -0,0 +1,320 @@
>> +/*
>> + * RTAS backend for RPA-compliant PP64 platform
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License as published by
>> + * the Free Software Foundation; either version 2 of the License, or (at
>> + * your option) any later version.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/moduleparam.h>
>> +#include <linux/pci.h>
>> +#include <linux/pci_hotplug.h>
>> +#include <linux/smp.h>
>> +#include <linux/init.h>
>> +#include <linux/vmalloc.h>
>> +#include <asm/eeh.h>
>> +#include <asm/rtas.h>
>> +#include <asm/pci-bridge.h>
>> +
>> +#include "../pci.h"
>> +#include "rpaphp.h"
>> +
>> +#define	RPA_PHP_DR_INDICATOR	9002
>> +#define RPA_PHP_DR_ENTITY_SENSE	9003
>> +
>> +static int get_power_status(struct hotplug_slot *hp_slot, u8 *val)
>> +{
>> +	struct rpa_php_slot *slot = hp_slot->private;
>> +	int state, ret;
>> +
>> +	/* By default, the power is on */
>> +	*val = RPA_PHP_SLOT_POWER_ON;
>> +
>> +	/* Retrieve power state from firmware, which might fail */
>> +	ret = rtas_get_power_level(slot->power_domain, &state);
>> +	if (!ret) {
>> +		if (state > 0)
>> +			hp_slot->info->power_status = RPA_PHP_SLOT_POWER_ON;
>> +		else
>> +			hp_slot->info->power_status = RPA_PHP_SLOT_POWER_OFF;
>> +		*val = hp_slot->info->power_status;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int get_adapter_status(struct hotplug_slot *hp_slot, u8 *val)
>> +{
>> +	struct rpa_php_slot *slot = hp_slot->private;
>> +        int state, ret;
>> +
>> +	/* By default, the slot is empty */
>> +	*val = RPA_PHP_SLOT_EMPTY;
>> +
>> +	/* Retrieve presence from firmware */
>> +	ret = rtas_get_sensor(RPA_PHP_DR_ENTITY_SENSE, slot->index, &state);
>> +	if (ret >= 0) {
>> +		if (state > 0)
>> +			hp_slot->info->adapter_status = RPA_PHP_SLOT_PRESENT;
>> +		else
>> +			hp_slot->info->adapter_status = RPA_PHP_SLOT_EMPTY;
>> +		*val = hp_slot->info->adapter_status;
>> +		return 0;
>> +	}
>> +
>> +	/* Check if we need power slot on and retry */
>> +	if (ret != -EFAULT && ret != -EEXIST) {
>> +		err("%s: Error %d getting slot[%s] presence\n",
>> +		    __func__, ret, slot->name);
>> +		return ret;
>> +	}
>> +
>> +	/* Power slot on, which might fail */
>> +	ret = rtas_set_power_level(slot->power_domain,
>> +				   RPA_PHP_SLOT_POWER_ON, &state);
>> +	if (!ret)
>> +		hp_slot->info->power_status = RPA_PHP_SLOT_POWER_ON;
>> +
>> +	/* Recheck the presence */
>> +	ret = rtas_get_sensor(RPA_PHP_DR_ENTITY_SENSE, slot->index, &state);
>> +	if (ret >= 0) {
>> +		if (state > 0)
>> +			hp_slot->info->adapter_status = RPA_PHP_SLOT_PRESENT;
>> +		else
>> +			hp_slot->info->adapter_status = RPA_PHP_SLOT_EMPTY;
>> +		*val = hp_slot->info->adapter_status;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +static int set_attention_status(struct hotplug_slot *hp_slot, u8 val)
>> +{
>> +	struct rpa_php_slot *slot = hp_slot->private;
>> +	int ret;
>> +
>> +	/*
>> +	 * The default operation would to turn on
>> +	 * the attention
>> +	 */
>> +	switch (val) {
>> +	case RPA_PHP_SLOT_ATTEN_OFF:
>> +	case RPA_PHP_SLOT_ATTEN_ON:
>> +	case RPA_PHP_SLOT_ATTEN_IND:
>> +	case RPA_PHP_SLOT_ATTEN_ACT:
>> +		break;
>> +	default:
>> +		val = RPA_PHP_SLOT_ATTEN_ON;
>> +	}
>> +
>> +	/* Set the attention */
>> +	ret = rtas_set_indicator(RPA_PHP_DR_INDICATOR, slot->index, val);
>> +	if (!ret)
>> +		hp_slot->info->attention_status = val;
>> +
>> +	return ret;
>> +}
>> +
>> +static enum pci_bus_speed get_max_bus_speed(struct rpa_php_slot *slot)
>> +{
>> +	enum pci_bus_speed speed;
>> +
>> +	switch (slot->type) {
>> +	case 1 ... 6:
>> +		speed = PCI_SPEED_33MHz;
>> +		break;
>> +	case 7 ... 8:
>> +		speed = PCI_SPEED_66MHz;
>> +		break;
>> +	case 11:
>> +	case 14:
>> +		speed = PCI_SPEED_66MHz_PCIX;
>> +		break;
>> +	case 12:
>> +	case 15:
>> +		speed = PCI_SPEED_100MHz_PCIX;
>> +		break;
>> +	case 13:
>> +	case 16:
>> +		speed = PCI_SPEED_133MHz_PCIX;
>> +		break;
>> +	default:
>> +		speed = PCI_SPEED_UNKNOWN;
>> +	}
>> +
>> +	return speed;
>> +}
>> +
>> +static int enable_slot(struct hotplug_slot *hp_slot)
>> +{
>> +	struct rpa_php_slot *slot = hp_slot->private;
>> +	uint8_t presence;
>> +	int ret;
>> +
>> +	/* Check if the slot has been configured */
>> +	if (slot->state == RPA_PHP_SLOT_CONFIGURED)
>> +		return 0;
>> +
>> +	/* Retrieve slot presence status */
>> +	ret = hp_slot->ops->get_adapter_status(hp_slot, &presence);
>> +	if (ret)
>> +		return ret;
>> +
>> +	switch (presence) {
>> +	case RPA_PHP_SLOT_PRESENT:
>> +		pci_lock_rescan_remove();
>> +		pcibios_add_pci_devices(slot->bus);
>> +		pci_unlock_rescan_remove();
>> +		slot->state = RPA_PHP_SLOT_CONFIGURED;
>> +		break;
>> +	case RPA_PHP_SLOT_EMPTY:
>> +		slot->state = RPA_PHP_SLOT_NOT_CONFIGURED;
>> +		break;
>> +	default:
>> +		slot->state = RPA_PHP_SLOT_NOT_VALID;
>> +		return -EINVAL;
>> +	}
>> +
>> +	/* Fix the bus maximal speed */
>> +	slot->bus->max_bus_speed = get_max_bus_speed(slot);
>> +	return 0;
>> +}
>> +
>> +static int disable_slot(struct hotplug_slot *hp_slot)
>> +{
>> +	struct rpa_php_slot *slot = hp_slot->private;
>> +
>> +	if (slot->state != RPA_PHP_SLOT_CONFIGURED)
>> +		return 0;
>> +
>> +	pci_lock_rescan_remove();
>> +	pcibios_remove_pci_devices(slot->bus);
>> +	pci_unlock_rescan_remove();
>> +	vm_unmap_aliases();
>> +
>> +	slot->state = RPA_PHP_SLOT_NOT_CONFIGURED;
>> +	return 0;
>> +}
>> +
>> +static struct hotplug_slot_ops rpaphp_rtas_ops = {
>> +	.enable_slot		= enable_slot,
>> +	.disable_slot		= disable_slot,
>> +	.set_attention_status	= set_attention_status,
>> +	.get_power_status	= get_power_status,
>> +	.get_adapter_status	= get_adapter_status,
>> +};
>> +
>> +static int parse_drc_props(struct device_node *dn, u32 drc_index,
>> +                           char **drc_name, char **drc_type, u32 *drc_power)
>> +{
>> +	const u32 *indexes, *names, *types, *domains;
>> +	char *name, *type;
>> +	struct device_node *parent = dn;
>> +	u32 i;
>> +
>> +	while ((parent = of_get_parent(parent))) {
>> +		indexes = of_get_property(parent, "ibm,drc-indexes", NULL);
>> +		names   = of_get_property(parent, "ibm,drc-names", NULL);
>> +		types   = of_get_property(parent, "ibm,drc-types", NULL);
>> +		domains = of_get_property(parent, "ibm,drc-power-domains", NULL);
>> +
>> +		if (!indexes || !names || !types || !domains) {
>> +			of_node_put(parent);
>> +			continue;
>> +		}
>> +
>> +		name = (char *)&names[1];
>> +		type = (char *)&types[1];
>> +		for (i = 0; i < be32_to_cpu(indexes[0]); i++) {
>> +			if (be32_to_cpu(indexes[i + 1]) != drc_index) {
>> +				name += (strlen(name) + 1);
>> +				type += (strlen(type) + 1);
>> +				continue;
>> +			}
>> +
>> +			/* Matched index */
>> +			if (drc_name)
>> +				*drc_name = name;
>> +			if (drc_type)
>> +				*drc_type = type;
>> +			if (drc_power)
>> +				*drc_power = be32_to_cpu(domains[i + 1]);
>> +
>> +			of_node_put(parent);
>> +			return 0;
>> +		}
>> +
>> +		/* Next level parent */
>> +		of_node_put(parent);
>> +	}
>> +
>> +	return -ENODEV;
>> +}
>> +
>> +/*
>> + * To get the DRC props describing the current node, first obtain it's
>> + * my-drc-index property.  Next obtain the DRC list from it's parent.  Use
>> + * the my-drc-index for correlation, and obtain the requested properties.
>> + */
>> +int rpaphp_get_drc_props(struct device_node *dn, int *drc_index,
>> +                         char **drc_name, char **drc_type, int *drc_power)
>> +{
>> +	const u32 *my_index;
>> +
>> +	/* Check if node is capable of hotplug */
>> +	my_index = of_get_property(dn, "ibm,my-drc-index", NULL);
>> +	if (!my_index)
>> +		return -EINVAL;
>> +	if (drc_index)
>> +		*drc_index = be32_to_cpu(*my_index);
>> +
>> +	return parse_drc_props(dn, be32_to_cpu(*my_index),
>> +			       drc_name, drc_type, drc_power);
>> +}
>> +EXPORT_SYMBOL_GPL(rpaphp_get_drc_props);
>> +
>> +struct rpa_php_slot *rpaphp_rtas_add_slot(struct device_node *dn)
>> +{
>> +	char *name, *type, *endptr;
>> +	int index, power_domain;
>> +	struct rpa_php_slot *slot;
>> +	struct pci_bus *bus;
>> +	int val, ret;
>> +
>> +	/* Get and parse the hotplug properties */
>> +	ret = rpaphp_get_drc_props(dn, &index, &name, &type, &power_domain);
>> +	if (ret)
>> +		return NULL;
>> +
>> +	/*
>> +	 * PCI hotplug slots have integer DRC type. That of
>> +	 * PHB slot is fixed to "PHB"
>> +	 */
>> +        val = simple_strtoul(type, &endptr, 10);
>> +	if (strcmp(type, "PHB") && (endptr == type))
>> +		return NULL;
>> +
>> +	slot = alloc_slot_struct(dn, index, name, power_domain);
>> +	if (!slot)
>> +		return NULL;
>> +
>> +        /* The slot should have an associated bus */
>> +	bus = pcibios_find_pci_bus(dn);
>> +	if (!bus) {
>> +		err("%s: No PCI bus for device node %s\n",
>> +			__func__, dn->full_name);
>> +		goto fail;
>> +	}
>> +
>> +	slot->hotplug_slot->ops = &rpaphp_rtas_ops;
>> +	slot->type     = val;
>> +	slot->bus      = bus;
>> +	slot->pci_devs = &bus->devices;
>> +	return slot;
>> +fail:
>> +	dealloc_slot_struct(slot);
>> +	return NULL;
>> +}
>> diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
>> deleted file mode 100644
>> index be48e69..0000000
>> --- a/drivers/pci/hotplug/rpaphp_slot.c
>> +++ /dev/null
>> @@ -1,140 +0,0 @@
>> -/*
>> - * RPA Virtual I/O device functions
>> - * Copyright (C) 2004 Linda Xie <lxie at us.ibm.com>
>> - *
>> - * All rights reserved.
>> - *
>> - * This program is free software; you can redistribute it and/or modify
>> - * it under the terms of the GNU General Public License as published by
>> - * the Free Software Foundation; either version 2 of the License, or (at
>> - * your option) any later version.
>> - *
>> - * This program is distributed in the hope that it will be useful, but
>> - * WITHOUT ANY WARRANTY; without even the implied warranty of
>> - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
>> - * NON INFRINGEMENT.  See the GNU General Public License for more
>> - * details.
>> - *
>> - * You should have received a copy of the GNU General Public License
>> - * along with this program; if not, write to the Free Software
>> - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
>> - *
>> - * Send feedback to <lxie at us.ibm.com>
>> - *
>> - */
>> -#include <linux/kernel.h>
>> -#include <linux/module.h>
>> -#include <linux/sysfs.h>
>> -#include <linux/pci.h>
>> -#include <linux/string.h>
>> -#include <linux/slab.h>
>> -
>> -#include <asm/rtas.h>
>> -#include "rpaphp.h"
>> -
>> -/* free up the memory used by a slot */
>> -static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
>> -{
>> -	struct slot *slot = (struct slot *) hotplug_slot->private;
>> -	dealloc_slot_struct(slot);
>> -}
>> -
>> -void dealloc_slot_struct(struct slot *slot)
>> -{
>> -	kfree(slot->hotplug_slot->info);
>> -	kfree(slot->name);
>> -	kfree(slot->hotplug_slot);
>> -	kfree(slot);
>> -}
>> -
>> -struct slot *alloc_slot_struct(struct device_node *dn,
>> -                       int drc_index, char *drc_name, int power_domain)
>> -{
>> -	struct slot *slot;
>> -
>> -	slot = kzalloc(sizeof(struct slot), GFP_KERNEL);
>> -	if (!slot)
>> -		goto error_nomem;
>> -	slot->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
>> -	if (!slot->hotplug_slot)
>> -		goto error_slot;
>> -	slot->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
>> -					   GFP_KERNEL);
>> -	if (!slot->hotplug_slot->info)
>> -		goto error_hpslot;
>> -	slot->name = kstrdup(drc_name, GFP_KERNEL);
>> -	if (!slot->name)
>> -		goto error_info;
>> -	slot->dn = dn;
>> -	slot->index = drc_index;
>> -	slot->power_domain = power_domain;
>> -	slot->hotplug_slot->private = slot;
>> -	slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
>> -	slot->hotplug_slot->release = &rpaphp_release_slot;
>> -
>> -	return slot;
>> -
>> -error_info:
>> -	kfree(slot->hotplug_slot->info);
>> -error_hpslot:
>> -	kfree(slot->hotplug_slot);
>> -error_slot:
>> -	kfree(slot);
>> -error_nomem:
>> -	return NULL;
>> -}
>> -
>> -int rpaphp_deregister_slot(struct slot *slot)
>> -{
>> -	int retval = 0;
>> -	struct hotplug_slot *php_slot = slot->hotplug_slot;
>> -
>> -	 dbg("%s - Entry: deregistering slot=%s\n",
>> -		__func__, slot->name);
>> -
>> -	list_del(&slot->rpaphp_slot_list);
>> -
>> -	retval = pci_hp_deregister(php_slot);
>> -	if (retval)
>> -		err("Problem unregistering a slot %s\n", slot->name);
>> -
>> -	dbg("%s - Exit: rc[%d]\n", __func__, retval);
>> -	return retval;
>> -}
>> -EXPORT_SYMBOL_GPL(rpaphp_deregister_slot);
>> -
>> -int rpaphp_register_slot(struct slot *slot)
>> -{
>> -	struct hotplug_slot *php_slot = slot->hotplug_slot;
>> -	struct slot *tmp;
>> -	int retval;
>> -	int slotno;
>> -
>> -	dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n",
>> -		__func__, slot->dn->full_name, slot->index, slot->name,
>> -		slot->power_domain, slot->type);
>> -
>> -	/* Should not try to register the same slot twice */
>> -	list_for_each_entry(tmp, &rpaphp_slot_head, rpaphp_slot_list) {
>> -		if (!strcmp(tmp->name, slot->name)) {
>> -			err("%s: Slot[%s] is already registered\n",
>> -			    __func__, slot->name);
>> -			return -EAGAIN;
>> -		}
>> -	}
>> -
>> -	if (slot->dn->child)
>> -		slotno = PCI_SLOT(PCI_DN(slot->dn->child)->devfn);
>> -	else
>> -		slotno = -1;
>> -	retval = pci_hp_register(php_slot, slot->bus, slotno, slot->name);
>> -	if (retval) {
>> -		err("pci_hp_register failed with error %d\n", retval);
>> -		return retval;
>> -	}
>> -
>> -	/* add slot to our internal list */
>> -	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
>> -	info("Slot [%s] registered\n", slot->name);
>> -	return 0;
>> -}
>
>
>



More information about the Linuxppc-dev mailing list