Skip to content

Commit

Permalink
[PATCH] shpchp: fix improper mmio mapping
Browse files Browse the repository at this point in the history
Current SHPCHP driver seems not to map MMIO region properly. This
patch fixes this bug. This patch also cleanup the code.

Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Kenji Kaneshige authored and Greg Kroah-Hartman committed Jan 9, 2006
1 parent 87d6c55 commit 0455986
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 29 deletions.
3 changes: 3 additions & 0 deletions drivers/pci/hotplug/shpchp.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ struct controller {
enum pci_bus_speed speed;
u32 first_slot; /* First physical slot number */
u8 slot_bus; /* Bus where the slots handled by this controller sit */
u32 cap_offset;
unsigned long mmio_base;
unsigned long mmio_size;
};

struct hotplug_params {
Expand Down
2 changes: 0 additions & 2 deletions drivers/pci/hotplug/shpchp_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,6 @@ static int shpc_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_free_ctrl;
}

ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */

pci_set_drvdata(pdev, ctrl);

ctrl->pci_bus = kmalloc (sizeof (*ctrl->pci_bus), GFP_KERNEL);
Expand Down
73 changes: 46 additions & 27 deletions drivers/pci/hotplug/shpchp_hpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@ static void hpc_release_ctlr(struct controller *ctrl)
}
if (php_ctlr->pci_dev) {
iounmap(php_ctlr->creg);
release_mem_region(pci_resource_start(php_ctlr->pci_dev, 0), pci_resource_len(php_ctlr->pci_dev, 0));
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
php_ctlr->pci_dev = NULL;
}

Expand Down Expand Up @@ -1320,19 +1320,34 @@ static struct hpc_ops shpchp_hpc_ops = {
.check_cmd_status = hpc_check_cmd_status,
};

inline static int shpc_indirect_creg_read(struct controller *ctrl, int index,
u32 *value)
{
int rc;
u32 cap_offset = ctrl->cap_offset;
struct pci_dev *pdev = ctrl->pci_dev;

rc = pci_write_config_byte(pdev, cap_offset + DWORD_SELECT, index);
if (rc)
return rc;
return pci_read_config_dword(pdev, cap_offset + DWORD_DATA, value);
}

int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
{
struct php_ctlr_state_s *php_ctlr, *p;
void *instance_id = ctrl;
int rc;
int rc, num_slots = 0;
u8 hp_slot;
static int first = 1;
u32 shpc_cap_offset, shpc_base_offset;
u32 shpc_base_offset;
u32 tempdword, slot_reg;
u8 i;

DBG_ENTER_ROUTINE

ctrl->pci_dev = pdev; /* pci_dev of the P2P bridge */

spin_lock_init(&list_lock);
php_ctlr = (struct php_ctlr_state_s *) kmalloc(sizeof(struct php_ctlr_state_s), GFP_KERNEL);

Expand All @@ -1347,41 +1362,45 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)

if ((pdev->vendor == PCI_VENDOR_ID_AMD) || (pdev->device ==
PCI_DEVICE_ID_AMD_GOLAM_7450)) {
shpc_base_offset = 0; /* amd shpc driver doesn't use this; assume 0 */
/* 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);
} else {
if ((shpc_cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC)) == 0) {
err("%s : shpc_cap_offset == 0\n", __FUNCTION__);
ctrl->cap_offset = pci_find_capability(pdev, PCI_CAP_ID_SHPC);
if (!ctrl->cap_offset) {
err("%s : cap_offset == 0\n", __FUNCTION__);
goto abort_free_ctlr;
}
dbg("%s: shpc_cap_offset = %x\n", __FUNCTION__, shpc_cap_offset);
rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , BASE_OFFSET);
dbg("%s: cap_offset = %x\n", __FUNCTION__, ctrl->cap_offset);

rc = shpc_indirect_creg_read(ctrl, 0, &shpc_base_offset);
if (rc) {
err("%s : pci_word_config_byte failed\n", __FUNCTION__);
err("%s: cannot read base_offset\n", __FUNCTION__);
goto abort_free_ctlr;
}
rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &shpc_base_offset);

rc = shpc_indirect_creg_read(ctrl, 3, &tempdword);
if (rc) {
err("%s : pci_read_config_dword failed\n", __FUNCTION__);
err("%s: cannot read slot config\n", __FUNCTION__);
goto abort_free_ctlr;
}
num_slots = tempdword & SLOT_NUM;
dbg("%s: num_slots (indirect) %x\n", __FUNCTION__, num_slots);

for (i = 0; i <= 14; i++) {
rc = pci_write_config_byte(pdev, (u8)shpc_cap_offset + DWORD_SELECT , i);
if (rc) {
err("%s : pci_word_config_byte failed\n", __FUNCTION__);
goto abort_free_ctlr;
}

rc = pci_read_config_dword(pdev, (u8)shpc_cap_offset + DWORD_DATA, &tempdword);
for (i = 0; i < 9 + num_slots; i++) {
rc = shpc_indirect_creg_read(ctrl, i, &tempdword);
if (rc) {
err("%s : pci_read_config_dword failed\n", __FUNCTION__);
err("%s: cannot read creg (index = %d)\n",
__FUNCTION__, i);
goto abort_free_ctlr;
}
dbg("%s: offset %d: value %x\n", __FUNCTION__,i,
tempdword);
}

ctrl->mmio_base =
pci_resource_start(pdev, 0) + shpc_base_offset;
ctrl->mmio_size = 0x24 + 0x4 * num_slots;
}

if (first) {
Expand All @@ -1395,16 +1414,16 @@ int shpc_init(struct controller * ctrl, struct pci_dev * pdev)
if (pci_enable_device(pdev))
goto abort_free_ctlr;

if (!request_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0), MY_NAME)) {
if (!request_mem_region(ctrl->mmio_base, ctrl->mmio_size, MY_NAME)) {
err("%s: cannot reserve MMIO region\n", __FUNCTION__);
goto abort_free_ctlr;
}

php_ctlr->creg = ioremap(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0));
php_ctlr->creg = ioremap(ctrl->mmio_base, ctrl->mmio_size);
if (!php_ctlr->creg) {
err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__, pci_resource_len(pdev, 0),
pci_resource_start(pdev, 0) + shpc_base_offset);
release_mem_region(pci_resource_start(pdev, 0) + shpc_base_offset, pci_resource_len(pdev, 0));
err("%s: cannot remap MMIO region %lx @ %lx\n", __FUNCTION__,
ctrl->mmio_size, ctrl->mmio_base);
release_mem_region(ctrl->mmio_base, ctrl->mmio_size);
goto abort_free_ctlr;
}
dbg("%s: php_ctlr->creg %p\n", __FUNCTION__, php_ctlr->creg);
Expand Down

0 comments on commit 0455986

Please sign in to comment.