aboutsummaryrefslogtreecommitdiff
path: root/drivers/pci/hotplug/shpchp_hpc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/hotplug/shpchp_hpc.c')
-rw-r--r--drivers/pci/hotplug/shpchp_hpc.c210
1 files changed, 95 insertions, 115 deletions
diff --git a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
index 86dc3984776..29e22352822 100644
--- a/drivers/pci/hotplug/shpchp_hpc.c
+++ b/drivers/pci/hotplug/shpchp_hpc.c
@@ -113,10 +113,10 @@
#define CON_PFAULT_INTR_MASK (1 << 28)
#define MRL_CHANGE_SERR_MASK (1 << 29)
#define CON_PFAULT_SERR_MASK (1 << 30)
-#define SLOT_REG_RSVDZ_MASK (1 << 15) | (7 << 21)
+#define SLOT_REG_RSVDZ_MASK ((1 << 15) | (7 << 21))
/*
- * SHPC Command Code definitnions
+ * SHPC Command Code definitions
*
* Slot Operation 00h - 3Fh
* Set Bus Segment Speed/Mode A 40h - 47h
@@ -179,8 +179,6 @@
#define SLOT_EVENT_LATCH 0x2
#define SLOT_SERR_INT_MASK 0x3
-static atomic_t shpchp_num_controllers = ATOMIC_INIT(0);
-
static irqreturn_t shpc_isr(int irq, void *dev_id);
static void start_int_poll_timer(struct controller *ctrl, int sec);
static int hpc_check_cmd_status(struct controller *ctrl);
@@ -343,8 +341,7 @@ static int shpc_write_cmd(struct slot *slot, u8 t_slot, u8 cmd)
cmd_status = hpc_check_cmd_status(slot->ctrl);
if (cmd_status) {
- ctrl_err(ctrl,
- "Failed to issued command 0x%x (error code = %d)\n",
+ ctrl_err(ctrl, "Failed to issued command 0x%x (error code = %d)\n",
cmd, cmd_status);
retval = -EIO;
}
@@ -406,7 +403,7 @@ static int hpc_get_attention_status(struct slot *slot, u8 *status)
return 0;
}
-static int hpc_get_power_status(struct slot * slot, u8 *status)
+static int hpc_get_power_status(struct slot *slot, u8 *status)
{
struct controller *ctrl = slot->ctrl;
u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
@@ -530,7 +527,7 @@ static int hpc_get_mode1_ECC_cap(struct slot *slot, u8 *mode)
return retval;
}
-static int hpc_query_power_fault(struct slot * slot)
+static int hpc_query_power_fault(struct slot *slot)
{
struct controller *ctrl = slot->ctrl;
u32 slot_reg = shpc_readl(ctrl, SLOT_REG(slot->hp_slot));
@@ -614,16 +611,9 @@ static void hpc_release_ctlr(struct controller *ctrl)
iounmap(ctrl->creg);
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
-
- /*
- * If this is the last controller to be released, destroy the
- * shpchpd work queue
- */
- if (atomic_dec_and_test(&shpchp_num_controllers))
- destroy_workqueue(shpchp_wq);
}
-static int hpc_power_on_slot(struct slot * slot)
+static int hpc_power_on_slot(struct slot *slot)
{
int retval;
@@ -634,7 +624,7 @@ static int hpc_power_on_slot(struct slot * slot)
return retval;
}
-static int hpc_slot_enable(struct slot * slot)
+static int hpc_slot_enable(struct slot *slot)
{
int retval;
@@ -647,7 +637,7 @@ static int hpc_slot_enable(struct slot * slot)
return retval;
}
-static int hpc_slot_disable(struct slot * slot)
+static int hpc_slot_disable(struct slot *slot)
{
int retval;
@@ -660,7 +650,76 @@ static int hpc_slot_disable(struct slot * slot)
return retval;
}
-static int hpc_set_bus_speed_mode(struct slot * slot, enum pci_bus_speed value)
+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;
struct controller *ctrl = slot->ctrl;
@@ -720,6 +779,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 +864,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 +903,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 +920,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,
@@ -951,8 +943,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */
ctrl_dbg(ctrl, "Hotplug Controller:\n");
- if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
- PCI_DEVICE_ID_AMD_GOLAM_7450)) {
+ if (pdev->vendor == PCI_VENDOR_ID_AMD &&
+ pdev->device == PCI_DEVICE_ID_AMD_GOLAM_7450) {
/* amd shpc driver doesn't use Base Offset; assume 0 */
ctrl->mmio_base = pci_resource_start(pdev, 0);
ctrl->mmio_size = pci_resource_len(pdev, 0);
@@ -981,8 +973,8 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
for (i = 0; i < 9 + num_slots; i++) {
rc = shpc_indirect_read(ctrl, i, &tempdword);
if (rc) {
- ctrl_err(ctrl,
- "Cannot read creg (index = %d)\n", i);
+ ctrl_err(ctrl, "Cannot read creg (index = %d)\n",
+ i);
goto abort;
}
ctrl_dbg(ctrl, " offset %d: value %x\n", i, tempdword);
@@ -1067,36 +1059,24 @@ int shpc_init(struct controller *ctrl, struct pci_dev *pdev)
/* Installs the interrupt handler */
rc = pci_enable_msi(pdev);
if (rc) {
- ctrl_info(ctrl,
- "Can't get msi for the hotplug controller\n");
- ctrl_info(ctrl,
- "Use INTx for the hotplug controller\n");
+ ctrl_info(ctrl, "Can't get msi for the hotplug controller\n");
+ ctrl_info(ctrl, "Use INTx for the hotplug controller\n");
}
rc = request_irq(ctrl->pci_dev->irq, shpc_isr, IRQF_SHARED,
MY_NAME, (void *)ctrl);
- ctrl_dbg(ctrl, "request_irq %d for hpc%d (returns %d)\n",
- ctrl->pci_dev->irq,
- atomic_read(&shpchp_num_controllers), rc);
+ ctrl_dbg(ctrl, "request_irq %d (returns %d)\n",
+ ctrl->pci_dev->irq, rc);
if (rc) {
- ctrl_err(ctrl, "Can't get irq %d for the hotplug "
- "controller\n", ctrl->pci_dev->irq);
+ ctrl_err(ctrl, "Can't get irq %d for the hotplug controller\n",
+ ctrl->pci_dev->irq);
goto abort_iounmap;
}
}
ctrl_dbg(ctrl, "HPC at %s irq=%x\n", pci_name(pdev), pdev->irq);
- /*
- * If this is the first controller to be initialized,
- * initialize the shpchpd work queue
- */
- if (atomic_add_return(1, &shpchp_num_controllers) == 1) {
- shpchp_wq = create_singlethread_workqueue("shpchpd");
- if (!shpchp_wq) {
- rc = -ENOMEM;
- goto abort_iounmap;
- }
- }
+ shpc_get_max_bus_speed(ctrl);
+ shpc_get_cur_bus_speed(ctrl);
/*
* Unmask all event interrupts of all slots