mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	PCI: Make current and maximum bus speeds part of the PCI core
Move the max_bus_speed and cur_bus_speed into the pci_bus. Expose the values through the PCI slot driver instead of the hotplug slot driver. Update all the hotplug drivers to use the pci_bus instead of their own data structures. Signed-off-by: Matthew Wilcox <willy@linux.intel.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
		
							parent
							
								
									536c8cb49e
								
							
						
					
					
						commit
						3749c51ac6
					
				
					 17 changed files with 246 additions and 498 deletions
				
			
		| 
						 | 
				
			
			@ -332,8 +332,6 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot)
 | 
			
		|||
	slot->hotplug_slot->info->attention_status = 0;
 | 
			
		||||
	slot->hotplug_slot->info->latch_status = acpiphp_get_latch_status(slot->acpi_slot);
 | 
			
		||||
	slot->hotplug_slot->info->adapter_status = acpiphp_get_adapter_status(slot->acpi_slot);
 | 
			
		||||
	slot->hotplug_slot->info->max_bus_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
	slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
 | 
			
		||||
	acpiphp_slot->slot = slot;
 | 
			
		||||
	snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -310,8 +310,6 @@ struct controller {
 | 
			
		|||
	u8 first_slot;
 | 
			
		||||
	u8 add_support;
 | 
			
		||||
	u8 push_flag;
 | 
			
		||||
	enum pci_bus_speed speed;
 | 
			
		||||
	enum pci_bus_speed speed_capability;
 | 
			
		||||
	u8 push_button;			/* 0 = no pushbutton, 1 = pushbutton present */
 | 
			
		||||
	u8 slot_switch_type;		/* 0 = no switch, 1 = switch present */
 | 
			
		||||
	u8 defeature_PHP;		/* 0 = PHP not supported, 1 = PHP supported */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -583,30 +583,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_max_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	struct slot *slot = hotplug_slot->private;
 | 
			
		||||
	struct controller *ctrl = slot->ctrl;
 | 
			
		||||
 | 
			
		||||
	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 | 
			
		||||
 | 
			
		||||
	*value = ctrl->speed_capability;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	struct slot *slot = hotplug_slot->private;
 | 
			
		||||
	struct controller *ctrl = slot->ctrl;
 | 
			
		||||
 | 
			
		||||
	dbg("%s - physical_slot = %s\n", __func__, slot_name(slot));
 | 
			
		||||
 | 
			
		||||
	*value = ctrl->speed;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
 | 
			
		||||
	.set_attention_status =	set_attention_status,
 | 
			
		||||
	.enable_slot =		process_SI,
 | 
			
		||||
| 
						 | 
				
			
			@ -616,8 +592,6 @@ static struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {
 | 
			
		|||
	.get_attention_status =	get_attention_status,
 | 
			
		||||
	.get_latch_status =	get_latch_status,
 | 
			
		||||
	.get_adapter_status =	get_adapter_status,
 | 
			
		||||
	.get_max_bus_speed =	get_max_bus_speed,
 | 
			
		||||
	.get_cur_bus_speed =	get_cur_bus_speed,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SLOT_NAME_SIZE 10
 | 
			
		||||
| 
						 | 
				
			
			@ -629,6 +603,7 @@ static int ctrl_slot_setup(struct controller *ctrl,
 | 
			
		|||
	struct slot *slot;
 | 
			
		||||
	struct hotplug_slot *hotplug_slot;
 | 
			
		||||
	struct hotplug_slot_info *hotplug_slot_info;
 | 
			
		||||
	struct pci_bus *bus = ctrl->pci_bus;
 | 
			
		||||
	u8 number_of_slots;
 | 
			
		||||
	u8 slot_device;
 | 
			
		||||
	u8 slot_number;
 | 
			
		||||
| 
						 | 
				
			
			@ -694,7 +669,7 @@ static int ctrl_slot_setup(struct controller *ctrl,
 | 
			
		|||
			slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;
 | 
			
		||||
		if (is_slot66mhz(slot))
 | 
			
		||||
			slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;
 | 
			
		||||
		if (ctrl->speed == PCI_SPEED_66MHz)
 | 
			
		||||
		if (bus->cur_bus_speed == PCI_SPEED_66MHz)
 | 
			
		||||
			slot->capabilities |= PCISLOT_66_MHZ_OPERATION;
 | 
			
		||||
 | 
			
		||||
		ctrl_slot =
 | 
			
		||||
| 
						 | 
				
			
			@ -844,6 +819,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
	u32 rc;
 | 
			
		||||
	struct controller *ctrl;
 | 
			
		||||
	struct pci_func *func;
 | 
			
		||||
	struct pci_bus *bus;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = pci_enable_device(pdev);
 | 
			
		||||
| 
						 | 
				
			
			@ -852,6 +828,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
			pci_name(pdev), err);
 | 
			
		||||
		return err;
 | 
			
		||||
	}
 | 
			
		||||
	bus = pdev->subordinate;
 | 
			
		||||
 | 
			
		||||
	/* Need to read VID early b/c it's used to differentiate CPQ and INTC
 | 
			
		||||
	 * discovery
 | 
			
		||||
| 
						 | 
				
			
			@ -929,22 +906,22 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
			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;
 | 
			
		||||
				bus->max_bus_speed = PCI_SPEED_133MHz_PCIX;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			if (bus_cap & 0x40) {
 | 
			
		||||
				dbg("bus max supports 100MHz PCI-X\n");
 | 
			
		||||
				ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
 | 
			
		||||
				bus->max_bus_speed = PCI_SPEED_100MHz_PCIX;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			if (bus_cap & 20) {
 | 
			
		||||
				dbg("bus max supports 66MHz PCI-X\n");
 | 
			
		||||
				ctrl->speed_capability = PCI_SPEED_66MHz_PCIX;
 | 
			
		||||
				bus->max_bus_speed = PCI_SPEED_66MHz_PCIX;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			if (bus_cap & 10) {
 | 
			
		||||
				dbg("bus max supports 66MHz PCI\n");
 | 
			
		||||
				ctrl->speed_capability = PCI_SPEED_66MHz;
 | 
			
		||||
				bus->max_bus_speed = PCI_SPEED_66MHz;
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -955,7 +932,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
		case PCI_SUB_HPC_ID:
 | 
			
		||||
			/* Original 6500/7000 implementation */
 | 
			
		||||
			ctrl->slot_switch_type = 1;
 | 
			
		||||
			ctrl->speed_capability = PCI_SPEED_33MHz;
 | 
			
		||||
			bus->max_bus_speed = PCI_SPEED_33MHz;
 | 
			
		||||
			ctrl->push_button = 0;
 | 
			
		||||
			ctrl->pci_config_space = 1;
 | 
			
		||||
			ctrl->defeature_PHP = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -966,7 +943,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
			/* First Pushbutton implementation */
 | 
			
		||||
			ctrl->push_flag = 1;
 | 
			
		||||
			ctrl->slot_switch_type = 1;
 | 
			
		||||
			ctrl->speed_capability = PCI_SPEED_33MHz;
 | 
			
		||||
			bus->max_bus_speed = PCI_SPEED_33MHz;
 | 
			
		||||
			ctrl->push_button = 1;
 | 
			
		||||
			ctrl->pci_config_space = 1;
 | 
			
		||||
			ctrl->defeature_PHP = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -976,7 +953,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
		case PCI_SUB_HPC_ID_INTC:
 | 
			
		||||
			/* Third party (6500/7000) */
 | 
			
		||||
			ctrl->slot_switch_type = 1;
 | 
			
		||||
			ctrl->speed_capability = PCI_SPEED_33MHz;
 | 
			
		||||
			bus->max_bus_speed = PCI_SPEED_33MHz;
 | 
			
		||||
			ctrl->push_button = 0;
 | 
			
		||||
			ctrl->pci_config_space = 1;
 | 
			
		||||
			ctrl->defeature_PHP = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -987,7 +964,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
			/* First 66 Mhz implementation */
 | 
			
		||||
			ctrl->push_flag = 1;
 | 
			
		||||
			ctrl->slot_switch_type = 1;
 | 
			
		||||
			ctrl->speed_capability = PCI_SPEED_66MHz;
 | 
			
		||||
			bus->max_bus_speed = PCI_SPEED_66MHz;
 | 
			
		||||
			ctrl->push_button = 1;
 | 
			
		||||
			ctrl->pci_config_space = 1;
 | 
			
		||||
			ctrl->defeature_PHP = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -998,7 +975,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
			/* First PCI-X implementation, 100MHz */
 | 
			
		||||
			ctrl->push_flag = 1;
 | 
			
		||||
			ctrl->slot_switch_type = 1;
 | 
			
		||||
			ctrl->speed_capability = PCI_SPEED_100MHz_PCIX;
 | 
			
		||||
			bus->max_bus_speed = PCI_SPEED_100MHz_PCIX;
 | 
			
		||||
			ctrl->push_button = 1;
 | 
			
		||||
			ctrl->pci_config_space = 1;
 | 
			
		||||
			ctrl->defeature_PHP = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -1015,9 +992,9 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
	case PCI_VENDOR_ID_INTEL:
 | 
			
		||||
		/* Check for speed capability (0=33, 1=66) */
 | 
			
		||||
		if (subsystem_deviceid & 0x0001)
 | 
			
		||||
			ctrl->speed_capability = PCI_SPEED_66MHz;
 | 
			
		||||
			bus->max_bus_speed = PCI_SPEED_66MHz;
 | 
			
		||||
		else
 | 
			
		||||
			ctrl->speed_capability = PCI_SPEED_33MHz;
 | 
			
		||||
			bus->max_bus_speed = PCI_SPEED_33MHz;
 | 
			
		||||
 | 
			
		||||
		/* Check for push button */
 | 
			
		||||
		if (subsystem_deviceid & 0x0002)
 | 
			
		||||
| 
						 | 
				
			
			@ -1079,7 +1056,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
					pdev->bus->number);
 | 
			
		||||
 | 
			
		||||
	dbg("Hotplug controller capabilities:\n");
 | 
			
		||||
	dbg("    speed_capability       %d\n", ctrl->speed_capability);
 | 
			
		||||
	dbg("    speed_capability       %d\n", bus->max_bus_speed);
 | 
			
		||||
	dbg("    slot_switch_type       %s\n", ctrl->slot_switch_type ?
 | 
			
		||||
					"switch present" : "no switch");
 | 
			
		||||
	dbg("    defeature_PHP          %s\n", ctrl->defeature_PHP ?
 | 
			
		||||
| 
						 | 
				
			
			@ -1142,7 +1119,7 @@ static int cpqhpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/* Check for 66Mhz operation */
 | 
			
		||||
	ctrl->speed = get_controller_speed(ctrl);
 | 
			
		||||
	bus->cur_bus_speed = get_controller_speed(ctrl);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	/********************************************************
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1130,12 +1130,13 @@ static int is_bridge(struct pci_func * func)
 | 
			
		|||
static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_slot)
 | 
			
		||||
{
 | 
			
		||||
	struct slot *slot;
 | 
			
		||||
	struct pci_bus *bus = ctrl->pci_bus;
 | 
			
		||||
	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)
 | 
			
		||||
	if (bus->cur_bus_speed == adapter_speed)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	/* We don't allow freq/mode changes if we find another adapter running
 | 
			
		||||
| 
						 | 
				
			
			@ -1152,7 +1153,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
 | 
			
		|||
		 * lower speed/mode, we allow the new adapter to function at
 | 
			
		||||
		 * this rate if supported
 | 
			
		||||
		 */
 | 
			
		||||
		if (ctrl->speed < adapter_speed)
 | 
			
		||||
		if (bus->cur_bus_speed < adapter_speed)
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		return 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -1161,20 +1162,20 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
 | 
			
		|||
	/* 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))
 | 
			
		||||
	if ((bus->cur_bus_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))
 | 
			
		||||
	if ((bus->cur_bus_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)
 | 
			
		||||
	if (bus->max_bus_speed < adapter_speed) {
 | 
			
		||||
		if (bus->cur_bus_speed == bus->max_bus_speed)
 | 
			
		||||
			return 0;
 | 
			
		||||
		adapter_speed = ctrl->speed_capability;
 | 
			
		||||
		adapter_speed = bus->max_bus_speed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	writel(0x0L, ctrl->hpc_reg + LED_CONTROL);
 | 
			
		||||
| 
						 | 
				
			
			@ -1229,8 +1230,8 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
 | 
			
		|||
	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))) 
 | 
			
		||||
	if (((bus->cur_bus_speed == PCI_SPEED_66MHz) && (adapter_speed == PCI_SPEED_66MHz_PCIX)) ||
 | 
			
		||||
		((bus->cur_bus_speed == PCI_SPEED_66MHz_PCIX) && (adapter_speed == PCI_SPEED_66MHz))) 
 | 
			
		||||
			set_SOGO(ctrl);
 | 
			
		||||
 | 
			
		||||
	wait_for_ctrl_irq(ctrl);
 | 
			
		||||
| 
						 | 
				
			
			@ -1243,7 +1244,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
 | 
			
		|||
	set_SOGO(ctrl);
 | 
			
		||||
	wait_for_ctrl_irq(ctrl);
 | 
			
		||||
 | 
			
		||||
	ctrl->speed = adapter_speed;
 | 
			
		||||
	bus->cur_bus_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",
 | 
			
		||||
| 
						 | 
				
			
			@ -1269,6 +1270,7 @@ static u8 set_controller_speed(struct controller *ctrl, u8 adapter_speed, u8 hp_
 | 
			
		|||
 */
 | 
			
		||||
static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 | 
			
		||||
{
 | 
			
		||||
	struct pci_bus *bus = ctrl->pci_bus;
 | 
			
		||||
	u8 hp_slot;
 | 
			
		||||
	u8 temp_byte;
 | 
			
		||||
	u8 adapter_speed;
 | 
			
		||||
| 
						 | 
				
			
			@ -1309,7 +1311,7 @@ static u32 board_replaced(struct pci_func *func, struct controller *ctrl)
 | 
			
		|||
		wait_for_ctrl_irq (ctrl);
 | 
			
		||||
 | 
			
		||||
		adapter_speed = get_adapter_speed(ctrl, hp_slot);
 | 
			
		||||
		if (ctrl->speed != adapter_speed)
 | 
			
		||||
		if (bus->cur_bus_speed != adapter_speed)
 | 
			
		||||
			if (set_controller_speed(ctrl, adapter_speed, hp_slot))
 | 
			
		||||
				rc = WRONG_BUS_FREQUENCY;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1426,6 +1428,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 | 
			
		|||
	u32 temp_register = 0xFFFFFFFF;
 | 
			
		||||
	u32 rc = 0;
 | 
			
		||||
	struct pci_func *new_slot = NULL;
 | 
			
		||||
	struct pci_bus *bus = ctrl->pci_bus;
 | 
			
		||||
	struct slot *p_slot;
 | 
			
		||||
	struct resource_lists res_lists;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1456,7 +1459,7 @@ static u32 board_added(struct pci_func *func, struct controller *ctrl)
 | 
			
		|||
	wait_for_ctrl_irq (ctrl);
 | 
			
		||||
 | 
			
		||||
	adapter_speed = get_adapter_speed(ctrl, hp_slot);
 | 
			
		||||
	if (ctrl->speed != adapter_speed)
 | 
			
		||||
	if (bus->cur_bus_speed != adapter_speed)
 | 
			
		||||
		if (set_controller_speed(ctrl, adapter_speed, hp_slot))
 | 
			
		||||
			rc = WRONG_BUS_FREQUENCY;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -395,89 +395,40 @@ static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value)
 | 
			
		|||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 | 
			
		||||
static int get_max_bus_speed(struct slot *slot)
 | 
			
		||||
{
 | 
			
		||||
	int rc = -ENODEV;
 | 
			
		||||
	struct slot *pslot;
 | 
			
		||||
	int rc;
 | 
			
		||||
	u8 mode = 0;
 | 
			
		||||
	enum pci_bus_speed speed;
 | 
			
		||||
	struct pci_bus *bus = slot->hotplug_slot->pci_slot->bus;
 | 
			
		||||
 | 
			
		||||
	debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__,
 | 
			
		||||
		hotplug_slot, value);
 | 
			
		||||
	debug("%s - Entry slot[%p]\n", __func__, slot);
 | 
			
		||||
 | 
			
		||||
	ibmphp_lock_operations();
 | 
			
		||||
	mode = slot->supported_bus_mode;
 | 
			
		||||
	speed = slot->supported_speed; 
 | 
			
		||||
	ibmphp_unlock_operations();
 | 
			
		||||
 | 
			
		||||
	if (hotplug_slot) {
 | 
			
		||||
		pslot = hotplug_slot->private;
 | 
			
		||||
		if (pslot) {
 | 
			
		||||
			rc = 0;
 | 
			
		||||
			mode = pslot->supported_bus_mode;
 | 
			
		||||
			*value = pslot->supported_speed; 
 | 
			
		||||
			switch (*value) {
 | 
			
		||||
	switch (speed) {
 | 
			
		||||
	case BUS_SPEED_33:
 | 
			
		||||
		break;
 | 
			
		||||
	case BUS_SPEED_66:
 | 
			
		||||
		if (mode == BUS_MODE_PCIX) 
 | 
			
		||||
					*value += 0x01;
 | 
			
		||||
			speed += 0x01;
 | 
			
		||||
		break;
 | 
			
		||||
	case BUS_SPEED_100:
 | 
			
		||||
	case BUS_SPEED_133:
 | 
			
		||||
				*value = pslot->supported_speed + 0x01;
 | 
			
		||||
		speed += 0x01;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		/* Note (will need to change): there would be soon 256, 512 also */
 | 
			
		||||
		rc = -ENODEV;
 | 
			
		||||
	}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ibmphp_unlock_operations();
 | 
			
		||||
	debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value);
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
	if (!rc)
 | 
			
		||||
		bus->max_bus_speed = speed;
 | 
			
		||||
 | 
			
		||||
static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	int rc = -ENODEV;
 | 
			
		||||
	struct slot *pslot;
 | 
			
		||||
	u8 mode = 0;
 | 
			
		||||
 | 
			
		||||
	debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__,
 | 
			
		||||
		hotplug_slot, value);
 | 
			
		||||
 | 
			
		||||
	ibmphp_lock_operations();
 | 
			
		||||
 | 
			
		||||
	if (hotplug_slot) {
 | 
			
		||||
		pslot = hotplug_slot->private;
 | 
			
		||||
		if (pslot) {
 | 
			
		||||
			rc = get_cur_bus_info(&pslot);
 | 
			
		||||
			if (!rc) {
 | 
			
		||||
				mode = pslot->bus_on->current_bus_mode;
 | 
			
		||||
				*value = pslot->bus_on->current_speed;
 | 
			
		||||
				switch (*value) {
 | 
			
		||||
				case BUS_SPEED_33:
 | 
			
		||||
					break;
 | 
			
		||||
				case BUS_SPEED_66:
 | 
			
		||||
					if (mode == BUS_MODE_PCIX) 
 | 
			
		||||
						*value += 0x01;
 | 
			
		||||
					else if (mode == BUS_MODE_PCI)
 | 
			
		||||
						;
 | 
			
		||||
					else
 | 
			
		||||
						*value = PCI_SPEED_UNKNOWN;
 | 
			
		||||
					break;
 | 
			
		||||
				case BUS_SPEED_100:
 | 
			
		||||
				case BUS_SPEED_133:
 | 
			
		||||
					*value += 0x01;
 | 
			
		||||
					break;
 | 
			
		||||
				default:
 | 
			
		||||
					/* Note of change: there would also be 256, 512 soon */
 | 
			
		||||
					rc = -ENODEV;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ibmphp_unlock_operations();
 | 
			
		||||
	debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value);
 | 
			
		||||
	debug("%s - Exit rc[%d] speed[%x]\n", __func__, rc, speed);
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -572,6 +523,7 @@ static int __init init_ops(void)
 | 
			
		|||
		if (slot_cur->bus_on->current_speed == 0xFF) 
 | 
			
		||||
			if (get_cur_bus_info(&slot_cur)) 
 | 
			
		||||
				return -1;
 | 
			
		||||
		get_max_bus_speed(slot_cur);
 | 
			
		||||
 | 
			
		||||
		if (slot_cur->ctrl->options == 0xFF)
 | 
			
		||||
			if (get_hpc_options(slot_cur, &slot_cur->ctrl->options))
 | 
			
		||||
| 
						 | 
				
			
			@ -655,6 +607,7 @@ static int validate(struct slot *slot_cur, int opn)
 | 
			
		|||
int ibmphp_update_slot_info(struct slot *slot_cur)
 | 
			
		||||
{
 | 
			
		||||
	struct hotplug_slot_info *info;
 | 
			
		||||
	struct pci_bus *bus = slot_cur->hotplug_slot->pci_slot->bus;
 | 
			
		||||
	int rc;
 | 
			
		||||
	u8 bus_speed;
 | 
			
		||||
	u8 mode;
 | 
			
		||||
| 
						 | 
				
			
			@ -700,8 +653,7 @@ int ibmphp_update_slot_info(struct slot *slot_cur)
 | 
			
		|||
			bus_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	info->cur_bus_speed = bus_speed;
 | 
			
		||||
	info->max_bus_speed = slot_cur->hotplug_slot->info->max_bus_speed;
 | 
			
		||||
	bus->cur_bus_speed = bus_speed;
 | 
			
		||||
	// To do: bus_names 
 | 
			
		||||
	
 | 
			
		||||
	rc = pci_hp_change_slot_info(slot_cur->hotplug_slot, info);
 | 
			
		||||
| 
						 | 
				
			
			@ -1326,8 +1278,6 @@ struct hotplug_slot_ops ibmphp_hotplug_slot_ops = {
 | 
			
		|||
	.get_attention_status =		get_attention_status,
 | 
			
		||||
	.get_latch_status =		get_latch_status,
 | 
			
		||||
	.get_adapter_status =		get_adapter_present,
 | 
			
		||||
	.get_max_bus_speed =		get_max_bus_speed,
 | 
			
		||||
	.get_cur_bus_speed =		get_cur_bus_speed,
 | 
			
		||||
/*	.get_max_adapter_speed =	get_max_adapter_speed,
 | 
			
		||||
	.get_bus_name_status =		get_bus_name,
 | 
			
		||||
*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,32 +64,6 @@ static int debug;
 | 
			
		|||
static LIST_HEAD(pci_hotplug_slot_list);
 | 
			
		||||
static DEFINE_MUTEX(pci_hp_mutex);
 | 
			
		||||
 | 
			
		||||
/* these strings match up with the values in pci_bus_speed */
 | 
			
		||||
static char *pci_bus_speed_strings[] = {
 | 
			
		||||
	"33 MHz PCI",		/* 0x00 */
 | 
			
		||||
	"66 MHz PCI",		/* 0x01 */
 | 
			
		||||
	"66 MHz PCI-X",		/* 0x02 */
 | 
			
		||||
	"100 MHz PCI-X",	/* 0x03 */
 | 
			
		||||
	"133 MHz PCI-X",	/* 0x04 */
 | 
			
		||||
	NULL,			/* 0x05 */
 | 
			
		||||
	NULL,			/* 0x06 */
 | 
			
		||||
	NULL,			/* 0x07 */
 | 
			
		||||
	NULL,			/* 0x08 */
 | 
			
		||||
	"66 MHz PCI-X 266",	/* 0x09 */
 | 
			
		||||
	"100 MHz PCI-X 266",	/* 0x0a */
 | 
			
		||||
	"133 MHz PCI-X 266",	/* 0x0b */
 | 
			
		||||
	NULL,			/* 0x0c */
 | 
			
		||||
	NULL,			/* 0x0d */
 | 
			
		||||
	NULL,			/* 0x0e */
 | 
			
		||||
	NULL,			/* 0x0f */
 | 
			
		||||
	NULL,			/* 0x10 */
 | 
			
		||||
	"66 MHz PCI-X 533",	/* 0x11 */
 | 
			
		||||
	"100 MHz PCI-X 533",	/* 0x12 */
 | 
			
		||||
	"133 MHz PCI-X 533",	/* 0x13 */
 | 
			
		||||
	"2.5 GT/s PCIe",	/* 0x14 */
 | 
			
		||||
	"5.0 GT/s PCIe",	/* 0x15 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_HOTPLUG_PCI_CPCI
 | 
			
		||||
extern int cpci_hotplug_init(int debug);
 | 
			
		||||
extern void cpci_hotplug_exit(void);
 | 
			
		||||
| 
						 | 
				
			
			@ -118,8 +92,6 @@ GET_STATUS(power_status, u8)
 | 
			
		|||
GET_STATUS(attention_status, u8)
 | 
			
		||||
GET_STATUS(latch_status, u8)
 | 
			
		||||
GET_STATUS(adapter_status, u8)
 | 
			
		||||
GET_STATUS(max_bus_speed, enum pci_bus_speed)
 | 
			
		||||
GET_STATUS(cur_bus_speed, enum pci_bus_speed)
 | 
			
		||||
 | 
			
		||||
static ssize_t power_read_file(struct pci_slot *slot, char *buf)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -263,60 +235,6 @@ static struct pci_slot_attribute hotplug_slot_attr_presence = {
 | 
			
		|||
	.show = presence_read_file,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static char *unknown_speed = "Unknown bus speed";
 | 
			
		||||
 | 
			
		||||
static ssize_t max_bus_speed_read_file(struct pci_slot *slot, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	char *speed_string;
 | 
			
		||||
	int retval;
 | 
			
		||||
	enum pci_bus_speed value;
 | 
			
		||||
	
 | 
			
		||||
	retval = get_max_bus_speed(slot->hotplug, &value);
 | 
			
		||||
	if (retval)
 | 
			
		||||
		goto exit;
 | 
			
		||||
 | 
			
		||||
	if (value == PCI_SPEED_UNKNOWN)
 | 
			
		||||
		speed_string = unknown_speed;
 | 
			
		||||
	else
 | 
			
		||||
		speed_string = pci_bus_speed_strings[value];
 | 
			
		||||
	
 | 
			
		||||
	retval = sprintf (buf, "%s\n", speed_string);
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct pci_slot_attribute hotplug_slot_attr_max_bus_speed = {
 | 
			
		||||
	.attr = {.name = "max_bus_speed", .mode = S_IFREG | S_IRUGO},
 | 
			
		||||
	.show = max_bus_speed_read_file,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static ssize_t cur_bus_speed_read_file(struct pci_slot *slot, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	char *speed_string;
 | 
			
		||||
	int retval;
 | 
			
		||||
	enum pci_bus_speed value;
 | 
			
		||||
 | 
			
		||||
	retval = get_cur_bus_speed(slot->hotplug, &value);
 | 
			
		||||
	if (retval)
 | 
			
		||||
		goto exit;
 | 
			
		||||
 | 
			
		||||
	if (value == PCI_SPEED_UNKNOWN)
 | 
			
		||||
		speed_string = unknown_speed;
 | 
			
		||||
	else
 | 
			
		||||
		speed_string = pci_bus_speed_strings[value];
 | 
			
		||||
	
 | 
			
		||||
	retval = sprintf (buf, "%s\n", speed_string);
 | 
			
		||||
 | 
			
		||||
exit:
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct pci_slot_attribute hotplug_slot_attr_cur_bus_speed = {
 | 
			
		||||
	.attr = {.name = "cur_bus_speed", .mode = S_IFREG | S_IRUGO},
 | 
			
		||||
	.show = cur_bus_speed_read_file,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static ssize_t test_write_file(struct pci_slot *pci_slot, const char *buf,
 | 
			
		||||
		size_t count)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -391,26 +309,6 @@ static bool has_adapter_file(struct pci_slot *pci_slot)
 | 
			
		|||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool has_max_bus_speed_file(struct pci_slot *pci_slot)
 | 
			
		||||
{
 | 
			
		||||
	struct hotplug_slot *slot = pci_slot->hotplug;
 | 
			
		||||
	if ((!slot) || (!slot->ops))
 | 
			
		||||
		return false;
 | 
			
		||||
	if (slot->ops->get_max_bus_speed)
 | 
			
		||||
		return true;
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool has_cur_bus_speed_file(struct pci_slot *pci_slot)
 | 
			
		||||
{
 | 
			
		||||
	struct hotplug_slot *slot = pci_slot->hotplug;
 | 
			
		||||
	if ((!slot) || (!slot->ops))
 | 
			
		||||
		return false;
 | 
			
		||||
	if (slot->ops->get_cur_bus_speed)
 | 
			
		||||
		return true;
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool has_test_file(struct pci_slot *pci_slot)
 | 
			
		||||
{
 | 
			
		||||
	struct hotplug_slot *slot = pci_slot->hotplug;
 | 
			
		||||
| 
						 | 
				
			
			@ -456,20 +354,6 @@ static int fs_add_slot(struct pci_slot *slot)
 | 
			
		|||
			goto exit_adapter;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (has_max_bus_speed_file(slot)) {
 | 
			
		||||
		retval = sysfs_create_file(&slot->kobj,
 | 
			
		||||
					&hotplug_slot_attr_max_bus_speed.attr);
 | 
			
		||||
		if (retval)
 | 
			
		||||
			goto exit_max_speed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (has_cur_bus_speed_file(slot)) {
 | 
			
		||||
		retval = sysfs_create_file(&slot->kobj,
 | 
			
		||||
					&hotplug_slot_attr_cur_bus_speed.attr);
 | 
			
		||||
		if (retval)
 | 
			
		||||
			goto exit_cur_speed;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (has_test_file(slot)) {
 | 
			
		||||
		retval = sysfs_create_file(&slot->kobj,
 | 
			
		||||
					   &hotplug_slot_attr_test.attr);
 | 
			
		||||
| 
						 | 
				
			
			@ -480,14 +364,6 @@ static int fs_add_slot(struct pci_slot *slot)
 | 
			
		|||
	goto exit;
 | 
			
		||||
 | 
			
		||||
exit_test:
 | 
			
		||||
	if (has_cur_bus_speed_file(slot))
 | 
			
		||||
		sysfs_remove_file(&slot->kobj,
 | 
			
		||||
				  &hotplug_slot_attr_cur_bus_speed.attr);
 | 
			
		||||
exit_cur_speed:
 | 
			
		||||
	if (has_max_bus_speed_file(slot))
 | 
			
		||||
		sysfs_remove_file(&slot->kobj,
 | 
			
		||||
				  &hotplug_slot_attr_max_bus_speed.attr);
 | 
			
		||||
exit_max_speed:
 | 
			
		||||
	if (has_adapter_file(slot))
 | 
			
		||||
		sysfs_remove_file(&slot->kobj,
 | 
			
		||||
				  &hotplug_slot_attr_presence.attr);
 | 
			
		||||
| 
						 | 
				
			
			@ -523,14 +399,6 @@ static void fs_remove_slot(struct pci_slot *slot)
 | 
			
		|||
		sysfs_remove_file(&slot->kobj,
 | 
			
		||||
				  &hotplug_slot_attr_presence.attr);
 | 
			
		||||
 | 
			
		||||
	if (has_max_bus_speed_file(slot))
 | 
			
		||||
		sysfs_remove_file(&slot->kobj,
 | 
			
		||||
				  &hotplug_slot_attr_max_bus_speed.attr);
 | 
			
		||||
 | 
			
		||||
	if (has_cur_bus_speed_file(slot))
 | 
			
		||||
		sysfs_remove_file(&slot->kobj,
 | 
			
		||||
				  &hotplug_slot_attr_cur_bus_speed.attr);
 | 
			
		||||
 | 
			
		||||
	if (has_test_file(slot))
 | 
			
		||||
		sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_test.attr);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,8 +69,6 @@ static int get_power_status	(struct hotplug_slot *slot, u8 *value);
 | 
			
		|||
static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
 | 
			
		||||
static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
 | 
			
		||||
static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
 | 
			
		||||
static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 | 
			
		||||
static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * release_slot - free up the memory used by a slot
 | 
			
		||||
| 
						 | 
				
			
			@ -113,8 +111,6 @@ static int init_slot(struct controller *ctrl)
 | 
			
		|||
	ops->disable_slot = disable_slot;
 | 
			
		||||
	ops->get_power_status = get_power_status;
 | 
			
		||||
	ops->get_adapter_status = get_adapter_status;
 | 
			
		||||
	ops->get_max_bus_speed = get_max_bus_speed;
 | 
			
		||||
	ops->get_cur_bus_speed = get_cur_bus_speed;
 | 
			
		||||
	if (MRL_SENS(ctrl))
 | 
			
		||||
		ops->get_latch_status = get_latch_status;
 | 
			
		||||
	if (ATTN_LED(ctrl)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -227,27 +223,6 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
 | 
			
		|||
	return pciehp_get_adapter_status(slot, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
 | 
			
		||||
				enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	struct slot *slot = hotplug_slot->private;
 | 
			
		||||
 | 
			
		||||
	ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
 | 
			
		||||
		 __func__, slot_name(slot));
 | 
			
		||||
 | 
			
		||||
	return pciehp_get_max_link_speed(slot, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	struct slot *slot = hotplug_slot->private;
 | 
			
		||||
 | 
			
		||||
	ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
 | 
			
		||||
		 __func__, slot_name(slot));
 | 
			
		||||
 | 
			
		||||
	return pciehp_get_cur_link_speed(slot, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int pciehp_probe(struct pcie_device *dev)
 | 
			
		||||
{
 | 
			
		||||
	int rc;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -492,6 +492,7 @@ int pciehp_power_on_slot(struct slot * slot)
 | 
			
		|||
	u16 slot_cmd;
 | 
			
		||||
	u16 cmd_mask;
 | 
			
		||||
	u16 slot_status;
 | 
			
		||||
	u16 lnk_status;
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
 | 
			
		||||
	/* Clear sticky power-fault bit from previous power failures */
 | 
			
		||||
| 
						 | 
				
			
			@ -523,6 +524,14 @@ int pciehp_power_on_slot(struct slot * slot)
 | 
			
		|||
	ctrl_dbg(ctrl, "%s: SLOTCTRL %x write cmd %x\n", __func__,
 | 
			
		||||
		 pci_pcie_cap(ctrl->pcie->port) + PCI_EXP_SLTCTL, slot_cmd);
 | 
			
		||||
 | 
			
		||||
	retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
 | 
			
		||||
	if (retval) {
 | 
			
		||||
		ctrl_err(ctrl, "%s: Cannot read LNKSTA register\n",
 | 
			
		||||
				__func__);
 | 
			
		||||
		return retval;
 | 
			
		||||
	}
 | 
			
		||||
	pcie_update_link_speed(ctrl->pcie->port->subordinate, lnk_status);
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -610,37 +619,6 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
 | 
			
		|||
	return IRQ_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pciehp_get_max_link_speed(struct slot *slot, enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	struct controller *ctrl = slot->ctrl;
 | 
			
		||||
	enum pci_bus_speed lnk_speed;
 | 
			
		||||
	u32	lnk_cap;
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
 | 
			
		||||
	retval = pciehp_readl(ctrl, PCI_EXP_LNKCAP, &lnk_cap);
 | 
			
		||||
	if (retval) {
 | 
			
		||||
		ctrl_err(ctrl, "%s: Cannot read LNKCAP register\n", __func__);
 | 
			
		||||
		return retval;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (lnk_cap & 0x000F) {
 | 
			
		||||
	case 1:
 | 
			
		||||
		lnk_speed = PCIE_SPEED_2_5GT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		lnk_speed = PCIE_SPEED_5_0GT;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		lnk_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*value = lnk_speed;
 | 
			
		||||
	ctrl_dbg(ctrl, "Max link speed = %d\n", lnk_speed);
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pciehp_get_max_lnk_width(struct slot *slot,
 | 
			
		||||
				 enum pcie_link_width *value)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -691,38 +669,6 @@ int pciehp_get_max_lnk_width(struct slot *slot,
 | 
			
		|||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pciehp_get_cur_link_speed(struct slot *slot, enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	struct controller *ctrl = slot->ctrl;
 | 
			
		||||
	enum pci_bus_speed lnk_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
	u16 lnk_status;
 | 
			
		||||
 | 
			
		||||
	retval = pciehp_readw(ctrl, PCI_EXP_LNKSTA, &lnk_status);
 | 
			
		||||
	if (retval) {
 | 
			
		||||
		ctrl_err(ctrl, "%s: Cannot read LNKSTATUS register\n",
 | 
			
		||||
			 __func__);
 | 
			
		||||
		return retval;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (lnk_status & PCI_EXP_LNKSTA_CLS) {
 | 
			
		||||
	case 1:
 | 
			
		||||
		lnk_speed = PCIE_SPEED_2_5GT;
 | 
			
		||||
		break;
 | 
			
		||||
	case 2:
 | 
			
		||||
		lnk_speed = PCIE_SPEED_5_0GT;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		lnk_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*value = lnk_speed;
 | 
			
		||||
	ctrl_dbg(ctrl, "Current link speed = %d\n", lnk_speed);
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pciehp_get_cur_lnk_width(struct slot *slot,
 | 
			
		||||
				 enum pcie_link_width *value)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -130,10 +130,9 @@ static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 * value)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 | 
			
		||||
static enum pci_bus_speed get_max_bus_speed(struct slot *slot)
 | 
			
		||||
{
 | 
			
		||||
	struct slot *slot = (struct slot *)hotplug_slot->private;
 | 
			
		||||
 | 
			
		||||
	enum pci_bus_speed speed;
 | 
			
		||||
	switch (slot->type) {
 | 
			
		||||
	case 1:
 | 
			
		||||
	case 2:
 | 
			
		||||
| 
						 | 
				
			
			@ -141,30 +140,30 @@ static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_spe
 | 
			
		|||
	case 4:
 | 
			
		||||
	case 5:
 | 
			
		||||
	case 6:
 | 
			
		||||
		*value = PCI_SPEED_33MHz;	/* speed for case 1-6 */
 | 
			
		||||
		speed = PCI_SPEED_33MHz;	/* speed for case 1-6 */
 | 
			
		||||
		break;
 | 
			
		||||
	case 7:
 | 
			
		||||
	case 8:
 | 
			
		||||
		*value = PCI_SPEED_66MHz;
 | 
			
		||||
		speed = PCI_SPEED_66MHz;
 | 
			
		||||
		break;
 | 
			
		||||
	case 11:
 | 
			
		||||
	case 14:
 | 
			
		||||
		*value = PCI_SPEED_66MHz_PCIX;
 | 
			
		||||
		speed = PCI_SPEED_66MHz_PCIX;
 | 
			
		||||
		break;
 | 
			
		||||
	case 12:
 | 
			
		||||
	case 15:
 | 
			
		||||
		*value = PCI_SPEED_100MHz_PCIX;
 | 
			
		||||
		speed = PCI_SPEED_100MHz_PCIX;
 | 
			
		||||
		break;
 | 
			
		||||
	case 13:
 | 
			
		||||
	case 16:
 | 
			
		||||
		*value = PCI_SPEED_133MHz_PCIX;
 | 
			
		||||
		speed = PCI_SPEED_133MHz_PCIX;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		*value = PCI_SPEED_UNKNOWN;
 | 
			
		||||
		speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
	return speed;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_children_props(struct device_node *dn, const int **drc_indexes,
 | 
			
		||||
| 
						 | 
				
			
			@ -408,6 +407,8 @@ static int enable_slot(struct hotplug_slot *hotplug_slot)
 | 
			
		|||
		slot->state = NOT_VALID;
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	slot->bus->max_bus_speed = get_max_bus_speed(slot);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -333,8 +333,6 @@ struct hpc_ops {
 | 
			
		|||
	int (*set_attention_status)(struct slot *slot, u8 status);
 | 
			
		||||
	int (*get_latch_status)(struct slot *slot, u8 *status);
 | 
			
		||||
	int (*get_adapter_status)(struct slot *slot, u8 *status);
 | 
			
		||||
	int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
 | 
			
		||||
	int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
 | 
			
		||||
	int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed);
 | 
			
		||||
	int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode);
 | 
			
		||||
	int (*get_prog_int)(struct slot *slot, u8 *prog_int);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,8 +65,6 @@ static int get_power_status	(struct hotplug_slot *slot, u8 *value);
 | 
			
		|||
static int get_attention_status	(struct hotplug_slot *slot, u8 *value);
 | 
			
		||||
static int get_latch_status	(struct hotplug_slot *slot, u8 *value);
 | 
			
		||||
static int get_adapter_status	(struct hotplug_slot *slot, u8 *value);
 | 
			
		||||
static int get_max_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 | 
			
		||||
static int get_cur_bus_speed	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 | 
			
		||||
 | 
			
		||||
static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
 | 
			
		||||
	.set_attention_status =	set_attention_status,
 | 
			
		||||
| 
						 | 
				
			
			@ -76,8 +74,6 @@ static struct hotplug_slot_ops shpchp_hotplug_slot_ops = {
 | 
			
		|||
	.get_attention_status =	get_attention_status,
 | 
			
		||||
	.get_latch_status =	get_latch_status,
 | 
			
		||||
	.get_adapter_status =	get_adapter_status,
 | 
			
		||||
	.get_max_bus_speed =	get_max_bus_speed,
 | 
			
		||||
	.get_cur_bus_speed =	get_cur_bus_speed,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -279,37 +275,6 @@ static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_max_bus_speed(struct hotplug_slot *hotplug_slot,
 | 
			
		||||
				enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	struct slot *slot = get_slot(hotplug_slot);
 | 
			
		||||
	int retval;
 | 
			
		||||
 | 
			
		||||
	ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
 | 
			
		||||
		 __func__, slot_name(slot));
 | 
			
		||||
 | 
			
		||||
	retval = slot->hpc_ops->get_max_bus_speed(slot, value);
 | 
			
		||||
	if (retval < 0)
 | 
			
		||||
		*value = PCI_SPEED_UNKNOWN;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_cur_bus_speed (struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	struct slot *slot = get_slot(hotplug_slot);
 | 
			
		||||
	int retval;
 | 
			
		||||
 | 
			
		||||
	ctrl_dbg(slot->ctrl, "%s: physical_slot = %s\n",
 | 
			
		||||
		 __func__, slot_name(slot));
 | 
			
		||||
 | 
			
		||||
	retval = slot->hpc_ops->get_cur_bus_speed(slot, value);
 | 
			
		||||
	if (retval < 0)
 | 
			
		||||
		*value = PCI_SPEED_UNKNOWN;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int is_shpc_capable(struct pci_dev *dev)
 | 
			
		||||
{
 | 
			
		||||
	if ((dev->vendor == PCI_VENDOR_ID_AMD) || (dev->device ==
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -285,17 +285,8 @@ static int board_added(struct slot *p_slot)
 | 
			
		|||
		return WRONG_BUS_FREQUENCY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp);
 | 
			
		||||
	if (rc) {
 | 
			
		||||
		ctrl_err(ctrl, "Can't get bus operation speed\n");
 | 
			
		||||
		return WRONG_BUS_FREQUENCY;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp);
 | 
			
		||||
	if (rc) {
 | 
			
		||||
		ctrl_err(ctrl, "Can't get max bus operation speed\n");
 | 
			
		||||
		msp = bsp;
 | 
			
		||||
	}
 | 
			
		||||
	bsp = ctrl->pci_dev->bus->cur_bus_speed;
 | 
			
		||||
	msp = ctrl->pci_dev->bus->max_bus_speed;
 | 
			
		||||
 | 
			
		||||
	/* Check if there are other slots or devices on the same bus */
 | 
			
		||||
	if (!list_empty(&ctrl->pci_dev->subordinate->devices))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -660,6 +660,75 @@ static int hpc_slot_disable(struct slot * slot)
 | 
			
		|||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int shpc_get_cur_bus_speed(struct controller *ctrl)
 | 
			
		||||
{
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
	struct pci_bus *bus = ctrl->pci_dev->subordinate;
 | 
			
		||||
	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
	u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG);
 | 
			
		||||
	u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
 | 
			
		||||
	u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7);
 | 
			
		||||
 | 
			
		||||
	if ((pi == 1) && (speed_mode > 4)) {
 | 
			
		||||
		retval = -ENODEV;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (speed_mode) {
 | 
			
		||||
	case 0x0:
 | 
			
		||||
		bus_speed = PCI_SPEED_33MHz;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x1:
 | 
			
		||||
		bus_speed = PCI_SPEED_66MHz;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x2:
 | 
			
		||||
		bus_speed = PCI_SPEED_66MHz_PCIX;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x3:
 | 
			
		||||
		bus_speed = PCI_SPEED_100MHz_PCIX;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x4:
 | 
			
		||||
		bus_speed = PCI_SPEED_133MHz_PCIX;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x5:
 | 
			
		||||
		bus_speed = PCI_SPEED_66MHz_PCIX_ECC;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x6:
 | 
			
		||||
		bus_speed = PCI_SPEED_100MHz_PCIX_ECC;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x7:
 | 
			
		||||
		bus_speed = PCI_SPEED_133MHz_PCIX_ECC;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x8:
 | 
			
		||||
		bus_speed = PCI_SPEED_66MHz_PCIX_266;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x9:
 | 
			
		||||
		bus_speed = PCI_SPEED_100MHz_PCIX_266;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0xa:
 | 
			
		||||
		bus_speed = PCI_SPEED_133MHz_PCIX_266;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0xb:
 | 
			
		||||
		bus_speed = PCI_SPEED_66MHz_PCIX_533;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0xc:
 | 
			
		||||
		bus_speed = PCI_SPEED_100MHz_PCIX_533;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0xd:
 | 
			
		||||
		bus_speed = PCI_SPEED_133MHz_PCIX_533;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		retval = -ENODEV;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 out:
 | 
			
		||||
	bus->cur_bus_speed = bus_speed;
 | 
			
		||||
	dbg("Current bus speed = %d\n", bus_speed);
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
 | 
			
		||||
{
 | 
			
		||||
	int retval;
 | 
			
		||||
| 
						 | 
				
			
			@ -720,6 +789,8 @@ static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
 | 
			
		|||
	retval = shpc_write_cmd(slot, 0, cmd);
 | 
			
		||||
	if (retval)
 | 
			
		||||
		ctrl_err(ctrl, "%s: Write command failed!\n", __func__);
 | 
			
		||||
	else
 | 
			
		||||
		shpc_get_cur_bus_speed(ctrl);
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -803,10 +874,10 @@ static irqreturn_t shpc_isr(int irq, void *dev_id)
 | 
			
		|||
	return IRQ_HANDLED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 | 
			
		||||
static int shpc_get_max_bus_speed(struct controller *ctrl)
 | 
			
		||||
{
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
	struct controller *ctrl = slot->ctrl;
 | 
			
		||||
	struct pci_bus *bus = ctrl->pci_dev->subordinate;
 | 
			
		||||
	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
	u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
 | 
			
		||||
	u32 slot_avail1 = shpc_readl(ctrl, SLOT_AVAIL1);
 | 
			
		||||
| 
						 | 
				
			
			@ -842,79 +913,12 @@ static int hpc_get_max_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 | 
			
		|||
			retval = -ENODEV;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*value = bus_speed;
 | 
			
		||||
	bus->max_bus_speed = bus_speed;
 | 
			
		||||
	ctrl_dbg(ctrl, "Max bus speed = %d\n", bus_speed);
 | 
			
		||||
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int hpc_get_cur_bus_speed (struct slot *slot, enum pci_bus_speed *value)
 | 
			
		||||
{
 | 
			
		||||
	int retval = 0;
 | 
			
		||||
	struct controller *ctrl = slot->ctrl;
 | 
			
		||||
	enum pci_bus_speed bus_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
	u16 sec_bus_reg = shpc_readw(ctrl, SEC_BUS_CONFIG);
 | 
			
		||||
	u8 pi = shpc_readb(ctrl, PROG_INTERFACE);
 | 
			
		||||
	u8 speed_mode = (pi == 2) ? (sec_bus_reg & 0xF) : (sec_bus_reg & 0x7);
 | 
			
		||||
 | 
			
		||||
	if ((pi == 1) && (speed_mode > 4)) {
 | 
			
		||||
		*value = PCI_SPEED_UNKNOWN;
 | 
			
		||||
		return -ENODEV;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (speed_mode) {
 | 
			
		||||
	case 0x0:
 | 
			
		||||
		*value = PCI_SPEED_33MHz;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x1:
 | 
			
		||||
		*value = PCI_SPEED_66MHz;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x2:
 | 
			
		||||
		*value = PCI_SPEED_66MHz_PCIX;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x3:
 | 
			
		||||
		*value = PCI_SPEED_100MHz_PCIX;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x4:
 | 
			
		||||
		*value = PCI_SPEED_133MHz_PCIX;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x5:
 | 
			
		||||
		*value = PCI_SPEED_66MHz_PCIX_ECC;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x6:
 | 
			
		||||
		*value = PCI_SPEED_100MHz_PCIX_ECC;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x7:
 | 
			
		||||
		*value = PCI_SPEED_133MHz_PCIX_ECC;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x8:
 | 
			
		||||
		*value = PCI_SPEED_66MHz_PCIX_266;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0x9:
 | 
			
		||||
		*value = PCI_SPEED_100MHz_PCIX_266;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0xa:
 | 
			
		||||
		*value = PCI_SPEED_133MHz_PCIX_266;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0xb:
 | 
			
		||||
		*value = PCI_SPEED_66MHz_PCIX_533;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0xc:
 | 
			
		||||
		*value = PCI_SPEED_100MHz_PCIX_533;
 | 
			
		||||
		break;
 | 
			
		||||
	case 0xd:
 | 
			
		||||
		*value = PCI_SPEED_133MHz_PCIX_533;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		*value = PCI_SPEED_UNKNOWN;
 | 
			
		||||
		retval = -ENODEV;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctrl_dbg(ctrl, "Current bus speed = %d\n", bus_speed);
 | 
			
		||||
	return retval;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct hpc_ops shpchp_hpc_ops = {
 | 
			
		||||
	.power_on_slot			= hpc_power_on_slot,
 | 
			
		||||
	.slot_enable			= hpc_slot_enable,
 | 
			
		||||
| 
						 | 
				
			
			@ -926,8 +930,6 @@ static struct hpc_ops shpchp_hpc_ops = {
 | 
			
		|||
	.get_latch_status		= hpc_get_latch_status,
 | 
			
		||||
	.get_adapter_status		= hpc_get_adapter_status,
 | 
			
		||||
 | 
			
		||||
	.get_max_bus_speed		= hpc_get_max_bus_speed,
 | 
			
		||||
	.get_cur_bus_speed		= hpc_get_cur_bus_speed,
 | 
			
		||||
	.get_adapter_speed		= hpc_get_adapter_speed,
 | 
			
		||||
	.get_mode1_ECC_cap		= hpc_get_mode1_ECC_cap,
 | 
			
		||||
	.get_prog_int			= hpc_get_prog_int,
 | 
			
		||||
| 
						 | 
				
			
			@ -1086,6 +1088,9 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
 | 
			
		|||
	}
 | 
			
		||||
	ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq);
 | 
			
		||||
 | 
			
		||||
	shpc_get_max_bus_speed(ctrl);
 | 
			
		||||
	shpc_get_cur_bus_speed(ctrl);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If this is the first controller to be initialized,
 | 
			
		||||
	 * initialize the shpchpd work queue
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -387,10 +387,37 @@ static struct pci_bus * pci_alloc_bus(void)
 | 
			
		|||
		INIT_LIST_HEAD(&b->children);
 | 
			
		||||
		INIT_LIST_HEAD(&b->devices);
 | 
			
		||||
		INIT_LIST_HEAD(&b->slots);
 | 
			
		||||
		b->max_bus_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
		b->cur_bus_speed = PCI_SPEED_UNKNOWN;
 | 
			
		||||
	}
 | 
			
		||||
	return b;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static unsigned char pcie_link_speed[] = {
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* 0 */
 | 
			
		||||
	PCIE_SPEED_2_5GT,		/* 1 */
 | 
			
		||||
	PCIE_SPEED_5_0GT,		/* 2 */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* 3 */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* 4 */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* 5 */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* 6 */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* 7 */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* 8 */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* 9 */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* A */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* B */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* C */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* D */
 | 
			
		||||
	PCI_SPEED_UNKNOWN,		/* E */
 | 
			
		||||
	PCI_SPEED_UNKNOWN		/* F */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void pcie_update_link_speed(struct pci_bus *bus, u16 linksta)
 | 
			
		||||
{
 | 
			
		||||
	bus->cur_bus_speed = pcie_link_speed[linksta & 0xf];
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(pcie_update_link_speed);
 | 
			
		||||
 | 
			
		||||
static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
 | 
			
		||||
					   struct pci_dev *bridge, int busnr)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,54 @@ static ssize_t address_read_file(struct pci_slot *slot, char *buf)
 | 
			
		|||
				slot->number);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* these strings match up with the values in pci_bus_speed */
 | 
			
		||||
static char *pci_bus_speed_strings[] = {
 | 
			
		||||
	"33 MHz PCI",		/* 0x00 */
 | 
			
		||||
	"66 MHz PCI",		/* 0x01 */
 | 
			
		||||
	"66 MHz PCI-X", 	/* 0x02 */
 | 
			
		||||
	"100 MHz PCI-X",	/* 0x03 */
 | 
			
		||||
	"133 MHz PCI-X",	/* 0x04 */
 | 
			
		||||
	NULL,			/* 0x05 */
 | 
			
		||||
	NULL,			/* 0x06 */
 | 
			
		||||
	NULL,			/* 0x07 */
 | 
			
		||||
	NULL,			/* 0x08 */
 | 
			
		||||
	"66 MHz PCI-X 266",	/* 0x09 */
 | 
			
		||||
	"100 MHz PCI-X 266",	/* 0x0a */
 | 
			
		||||
	"133 MHz PCI-X 266",	/* 0x0b */
 | 
			
		||||
	NULL,			/* 0x0c */
 | 
			
		||||
	NULL,			/* 0x0d */
 | 
			
		||||
	NULL,			/* 0x0e */
 | 
			
		||||
	NULL,			/* 0x0f */
 | 
			
		||||
	NULL,			/* 0x10 */
 | 
			
		||||
	"66 MHz PCI-X 533",	/* 0x11 */
 | 
			
		||||
	"100 MHz PCI-X 533",	/* 0x12 */
 | 
			
		||||
	"133 MHz PCI-X 533",	/* 0x13 */
 | 
			
		||||
	"2.5 GT/s PCIe",	/* 0x14 */
 | 
			
		||||
	"5.0 GT/s PCIe",	/* 0x15 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static ssize_t bus_speed_read(enum pci_bus_speed speed, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	const char *speed_string;
 | 
			
		||||
 | 
			
		||||
	if (speed < ARRAY_SIZE(pci_bus_speed_strings))
 | 
			
		||||
		speed_string = pci_bus_speed_strings[speed];
 | 
			
		||||
	else
 | 
			
		||||
		speed_string = "Unknown";
 | 
			
		||||
 | 
			
		||||
	return sprintf(buf, "%s\n", speed_string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t max_speed_read_file(struct pci_slot *slot, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	return bus_speed_read(slot->bus->max_bus_speed, buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static ssize_t cur_speed_read_file(struct pci_slot *slot, char *buf)
 | 
			
		||||
{
 | 
			
		||||
	return bus_speed_read(slot->bus->cur_bus_speed, buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pci_slot_release(struct kobject *kobj)
 | 
			
		||||
{
 | 
			
		||||
	struct pci_dev *dev;
 | 
			
		||||
| 
						 | 
				
			
			@ -66,9 +114,15 @@ static void pci_slot_release(struct kobject *kobj)
 | 
			
		|||
 | 
			
		||||
static struct pci_slot_attribute pci_slot_attr_address =
 | 
			
		||||
	__ATTR(address, (S_IFREG | S_IRUGO), address_read_file, NULL);
 | 
			
		||||
static struct pci_slot_attribute pci_slot_attr_max_speed =
 | 
			
		||||
	__ATTR(max_bus_speed, (S_IFREG | S_IRUGO), max_speed_read_file, NULL);
 | 
			
		||||
static struct pci_slot_attribute pci_slot_attr_cur_speed =
 | 
			
		||||
	__ATTR(cur_bus_speed, (S_IFREG | S_IRUGO), cur_speed_read_file, NULL);
 | 
			
		||||
 | 
			
		||||
static struct attribute *pci_slot_default_attrs[] = {
 | 
			
		||||
	&pci_slot_attr_address.attr,
 | 
			
		||||
	&pci_slot_attr_max_speed.attr,
 | 
			
		||||
	&pci_slot_attr_cur_speed.attr,
 | 
			
		||||
	NULL,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -380,6 +380,8 @@ struct pci_bus {
 | 
			
		|||
	unsigned char	primary;	/* number of primary bridge */
 | 
			
		||||
	unsigned char	secondary;	/* number of secondary bridge */
 | 
			
		||||
	unsigned char	subordinate;	/* max number of subordinate buses */
 | 
			
		||||
	unsigned char	max_bus_speed;	/* enum pci_bus_speed */
 | 
			
		||||
	unsigned char	cur_bus_speed;	/* enum pci_bus_speed */
 | 
			
		||||
 | 
			
		||||
	char		name[48];
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -610,6 +612,7 @@ struct pci_bus *pci_create_bus(struct device *parent, int bus,
 | 
			
		|||
			       struct pci_ops *ops, void *sysdata);
 | 
			
		||||
struct pci_bus *pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev,
 | 
			
		||||
				int busnr);
 | 
			
		||||
void pcie_update_link_speed(struct pci_bus *bus, u16 link_status);
 | 
			
		||||
struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr,
 | 
			
		||||
				 const char *name,
 | 
			
		||||
				 struct hotplug_slot *hotplug);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,12 +63,6 @@ enum pcie_link_width {
 | 
			
		|||
 * @get_adapter_status: Called to get see if an adapter is present in the slot or not.
 | 
			
		||||
 *	If this field is NULL, the value passed in the struct hotplug_slot_info
 | 
			
		||||
 *	will be used when this value is requested by a user.
 | 
			
		||||
 * @get_max_bus_speed: Called to get the max bus speed for a slot.
 | 
			
		||||
 *	If this field is NULL, the value passed in the struct hotplug_slot_info
 | 
			
		||||
 *	will be used when this value is requested by a user.
 | 
			
		||||
 * @get_cur_bus_speed: Called to get the current bus speed for a slot.
 | 
			
		||||
 *	If this field is NULL, the value passed in the struct hotplug_slot_info
 | 
			
		||||
 *	will be used when this value is requested by a user.
 | 
			
		||||
 *
 | 
			
		||||
 * The table of function pointers that is passed to the hotplug pci core by a
 | 
			
		||||
 * hotplug pci driver.  These functions are called by the hotplug pci core when
 | 
			
		||||
| 
						 | 
				
			
			@ -86,17 +80,14 @@ struct hotplug_slot_ops {
 | 
			
		|||
	int (*get_attention_status)	(struct hotplug_slot *slot, u8 *value);
 | 
			
		||||
	int (*get_latch_status)		(struct hotplug_slot *slot, u8 *value);
 | 
			
		||||
	int (*get_adapter_status)	(struct hotplug_slot *slot, u8 *value);
 | 
			
		||||
	int (*get_max_bus_speed)	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 | 
			
		||||
	int (*get_cur_bus_speed)	(struct hotplug_slot *slot, enum pci_bus_speed *value);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct hotplug_slot_info - used to notify the hotplug pci core of the state of the slot
 | 
			
		||||
 * @power: if power is enabled or not (1/0)
 | 
			
		||||
 * @power_status: if power is enabled or not (1/0)
 | 
			
		||||
 * @attention_status: if the attention light is enabled or not (1/0)
 | 
			
		||||
 * @latch_status: if the latch (if any) is open or closed (1/0)
 | 
			
		||||
 * @adapter_present: if there is a pci board present in the slot or not (1/0)
 | 
			
		||||
 * @address: (domain << 16 | bus << 8 | dev)
 | 
			
		||||
 * @adapter_status: if there is a pci board present in the slot or not (1/0)
 | 
			
		||||
 *
 | 
			
		||||
 * Used to notify the hotplug pci core of the status of a specific slot.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -105,8 +96,6 @@ struct hotplug_slot_info {
 | 
			
		|||
	u8	attention_status;
 | 
			
		||||
	u8	latch_status;
 | 
			
		||||
	u8	adapter_status;
 | 
			
		||||
	enum pci_bus_speed	max_bus_speed;
 | 
			
		||||
	enum pci_bus_speed	cur_bus_speed;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue