Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 181174
b: refs/heads/master
c: 9ad62ec
h: refs/heads/master
v: v3
  • Loading branch information
Paul Mundt committed Feb 3, 2010
1 parent 46e02fd commit 29b9aa7
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 37feecb0ae8c29b713b957c053b05ad10c42c73b
refs/heads/master: 9ad62ec4f752c82b39aa5927f23d894b46ae10b9
51 changes: 35 additions & 16 deletions trunk/arch/sh/drivers/pci/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,48 @@
#include <linux/timer.h>
#include <linux/kernel.h>

static int __init
early_read_config_word(struct pci_channel *hose,
int top_bus, int bus, int devfn, int offset, u16 *value)
/*
* These functions are used early on before PCI scanning is done
* and all of the pci_dev and pci_bus structures have been created.
*/
static struct pci_dev *fake_pci_dev(struct pci_channel *hose,
int top_bus, int busnr, int devfn)
{
struct pci_dev fake_dev;
struct pci_bus fake_bus;
static struct pci_dev dev;
static struct pci_bus bus;

fake_dev.bus = &fake_bus;
fake_dev.sysdata = hose;
fake_dev.devfn = devfn;
fake_bus.number = bus;
fake_bus.sysdata = hose;
fake_bus.ops = hose->pci_ops;
dev.bus = &bus;
dev.sysdata = hose;
dev.devfn = devfn;
bus.number = busnr;
bus.sysdata = hose;
bus.ops = hose->pci_ops;

if (bus != top_bus)
if(busnr != top_bus)
/* Fake a parent bus structure. */
fake_bus.parent = &fake_bus;
bus.parent = &bus;
else
fake_bus.parent = NULL;
bus.parent = NULL;

return pci_read_config_word(&fake_dev, offset, value);
return &dev;
}

#define EARLY_PCI_OP(rw, size, type) \
int __init early_##rw##_config_##size(struct pci_channel *hose, \
int top_bus, int bus, int devfn, int offset, type value) \
{ \
return pci_##rw##_config_##size( \
fake_pci_dev(hose, top_bus, bus, devfn), \
offset, value); \
}

EARLY_PCI_OP(read, byte, u8 *)
EARLY_PCI_OP(read, word, u16 *)
EARLY_PCI_OP(read, dword, u32 *)
EARLY_PCI_OP(write, byte, u8)
EARLY_PCI_OP(write, word, u16)
EARLY_PCI_OP(write, dword, u32)

int __init pci_is_66mhz_capable(struct pci_channel *hose,
int top_bus, int current_bus)
{
Expand Down Expand Up @@ -133,7 +152,7 @@ unsigned int pcibios_handle_status_errors(unsigned long addr,

/* Now back off of the IRQ for awhile */
if (hose->err_irq) {
disable_irq(hose->err_irq);
disable_irq_nosync(hose->err_irq);
hose->err_timer.expires = jiffies + HZ;
add_timer(&hose->err_timer);
}
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/sh/drivers/pci/pci-sh7780.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ static irqreturn_t sh7780_pci_serr_irq(int irq, void *dev_id)
__raw_writel(SH4_PCIINTM_SDIM, hose->reg_base + SH4_PCIINTM);

/* Back off the IRQ for awhile */
disable_irq(irq);
disable_irq_nosync(irq);
hose->serr_timer.expires = jiffies + HZ;
add_timer(&hose->serr_timer);

Expand Down
51 changes: 42 additions & 9 deletions trunk/arch/sh/drivers/pci/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ void pcibios_align_resource(void *data, struct resource *res,
}

void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
struct resource *res)
struct resource *res)
{
struct pci_channel *hose = dev->sysdata;
unsigned long offset = 0;
Expand All @@ -218,9 +218,8 @@ void pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
region->end = res->end - offset;
}

void __devinit
pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region)
void pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
struct pci_bus_region *region)
{
struct pci_channel *hose = dev->sysdata;
unsigned long offset = 0;
Expand Down Expand Up @@ -303,12 +302,41 @@ char * __devinit pcibios_setup(char *str)
return str;
}

static void __init
pcibios_bus_report_status_early(struct pci_channel *hose,
int top_bus, int current_bus,
unsigned int status_mask, int warn)
{
unsigned int pci_devfn;
u16 status;
int ret;

for (pci_devfn = 0; pci_devfn < 0xff; pci_devfn++) {
if (PCI_FUNC(pci_devfn))
continue;
ret = early_read_config_word(hose, top_bus, current_bus,
pci_devfn, PCI_STATUS, &status);
if (ret != PCIBIOS_SUCCESSFUL)
continue;
if (status == 0xffff)
continue;

early_write_config_word(hose, top_bus, current_bus,
pci_devfn, PCI_STATUS,
status & status_mask);
if (warn)
printk("(%02x:%02x: %04X) ", current_bus,
pci_devfn, status);
}
}

/*
* We can't use pci_find_device() here since we are
* called from interrupt context.
*/
static void pcibios_bus_report_status(struct pci_bus *bus,
unsigned int status_mask, int warn)
static void __init_refok
pcibios_bus_report_status(struct pci_bus *bus, unsigned int status_mask,
int warn)
{
struct pci_dev *dev;

Expand Down Expand Up @@ -341,12 +369,17 @@ static void pcibios_bus_report_status(struct pci_bus *bus,
pcibios_bus_report_status(dev->subordinate, status_mask, warn);
}

void pcibios_report_status(unsigned int status_mask, int warn)
void __init_refok pcibios_report_status(unsigned int status_mask, int warn)
{
struct pci_channel *hose;

for (hose = hose_head; hose; hose = hose->next)
pcibios_bus_report_status(hose->bus, status_mask, warn);
for (hose = hose_head; hose; hose = hose->next) {
if (unlikely(!hose->bus))
pcibios_bus_report_status_early(hose, hose_head->index,
hose->index, status_mask, warn);
else
pcibios_bus_report_status(hose->bus, status_mask, warn);
}
}

int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
Expand Down
12 changes: 12 additions & 0 deletions trunk/arch/sh/include/asm/pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ extern int register_pci_controller(struct pci_channel *hose);
extern void pcibios_report_status(unsigned int status_mask, int warn);

/* arch/sh/drivers/pci/common.c */
extern int early_read_config_byte(struct pci_channel *hose, int top_bus,
int bus, int devfn, int offset, u8 *value);
extern int early_read_config_word(struct pci_channel *hose, int top_bus,
int bus, int devfn, int offset, u16 *value);
extern int early_read_config_dword(struct pci_channel *hose, int top_bus,
int bus, int devfn, int offset, u32 *value);
extern int early_write_config_byte(struct pci_channel *hose, int top_bus,
int bus, int devfn, int offset, u8 value);
extern int early_write_config_word(struct pci_channel *hose, int top_bus,
int bus, int devfn, int offset, u16 value);
extern int early_write_config_dword(struct pci_channel *hose, int top_bus,
int bus, int devfn, int offset, u32 value);
extern void pcibios_enable_timers(struct pci_channel *hose);
extern unsigned int pcibios_handle_status_errors(unsigned long addr,
unsigned int status, struct pci_channel *hose);
Expand Down

0 comments on commit 29b9aa7

Please sign in to comment.