mirror of https://gitee.com/openkylin/linux.git
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
|
@ -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) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
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 New Issue