PCI: Make current and maximum bus speeds part of the PCI core
Matthew Wilcox [Sun, 13 Dec 2009 13:11:32 +0000 (08:11 -0500)]
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>

17 files changed:
drivers/pci/hotplug/acpiphp_core.c
drivers/pci/hotplug/cpqphp.h
drivers/pci/hotplug/cpqphp_core.c
drivers/pci/hotplug/cpqphp_ctrl.c
drivers/pci/hotplug/ibmphp_core.c
drivers/pci/hotplug/pci_hotplug_core.c
drivers/pci/hotplug/pciehp_core.c
drivers/pci/hotplug/pciehp_hpc.c
drivers/pci/hotplug/rpaphp_core.c
drivers/pci/hotplug/shpchp.h
drivers/pci/hotplug/shpchp_core.c
drivers/pci/hotplug/shpchp_ctrl.c
drivers/pci/hotplug/shpchp_hpc.c
drivers/pci/probe.c
drivers/pci/slot.c
include/linux/pci.h
include/linux/pci_hotplug.h

index 4dd7114..efa9f2d 100644 (file)
@@ -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);
index 9c6a9fd..d8ffc73 100644 (file)
@@ -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 */
index 075b4f4..f184d1d 100644 (file)
@@ -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);
 
 
        /********************************************************
index 0ff689a..e43908d 100644 (file)
@@ -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;
 
index 7485ffd..d934dd4 100644 (file)
@@ -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();
-
-       if (hotplug_slot) {
-               pslot = hotplug_slot->private;
-               if (pslot) {
-                       rc = 0;
-                       mode = pslot->supported_bus_mode;
-                       *value = pslot->supported_speed; 
-                       switch (*value) {
-                       case BUS_SPEED_33:
-                               break;
-                       case BUS_SPEED_66:
-                               if (mode == BUS_MODE_PCIX) 
-                                       *value += 0x01;
-                               break;
-                       case BUS_SPEED_100:
-                       case BUS_SPEED_133:
-                               *value = pslot->supported_speed + 0x01;
-                               break;
-                       default:
-                               /* Note (will need to change): there would be soon 256, 512 also */
-                               rc = -ENODEV;
-                       }
-               }
-       }
-
+       mode = slot->supported_bus_mode;
+       speed = slot->supported_speed; 
        ibmphp_unlock_operations();
-       debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value);
-       return rc;
-}
 
-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;
-                               }
-                       }
-               }
+       switch (speed) {
+       case BUS_SPEED_33:
+               break;
+       case BUS_SPEED_66:
+               if (mode == BUS_MODE_PCIX) 
+                       speed += 0x01;
+               break;
+       case BUS_SPEED_100:
+       case BUS_SPEED_133:
+               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);
+       if (!rc)
+               bus->max_bus_speed = speed;
+
+       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,
 */
index 38183a5..728b119 100644 (file)
@@ -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);
 
index 5674b20..920f820 100644 (file)
@@ -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;
index 6744ca1..40b48f5 100644 (file)
@@ -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)
 {
index c159223..b14e5e6 100644 (file)
@@ -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;
 }
 
index 8e210cd..d2627e1 100644 (file)
@@ -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);
index 8a520a3..a506229 100644 (file)
@@ -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 ==
index b8ab279..179b1c1 100644 (file)
@@ -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))
index 86dc398..5f5e8d2 100644 (file)
@@ -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
index dd64310..51cf898 100644 (file)
@@ -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)
 {
index 8c02b6c..6f6b8d2 100644 (file)
@@ -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,
 };
 
index d76a8a0..a446097 100644 (file)
@@ -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);
index 56251ac..5d09cba 100644 (file)
@@ -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;
 };
 
 /**