Commit 77257fe5 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: Tidy up various bits of the iSeries code. No significant code...

[PATCH] ppc64: Tidy up various bits of the iSeries code. No significant code changes, from Stephen Rothwell

From: Anton Blanchard <anton@samba.org>

Tidy up various bits of the iSeries code.  No significant code changes, from
Stephen Rothwell
parent 9a7dd652
...@@ -8,108 +8,29 @@ ...@@ -8,108 +8,29 @@
* (at your option) any later version. * (at your option) any later version.
*/ */
#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/slab.h>
#include <asm/system.h>
#include <asm/page.h> #include <asm/page.h>
#include <asm/abs_addr.h>
#include <asm/iSeries/HvCall.h> #include <asm/iSeries/HvCall.h>
#ifndef _HVCALLSC_H
#include <asm/iSeries/HvCallSc.h> #include <asm/iSeries/HvCallSc.h>
#endif
#include <asm/iSeries/LparData.h>
#ifndef _HVTYPES_H
#include <asm/iSeries/HvTypes.h> #include <asm/iSeries/HvTypes.h>
#endif
/*=====================================================================
* Note that this call takes at MOST one page worth of data
*/
int HvCall_readLogBuffer(HvLpIndex lpIndex, void *buffer, u64 bufLen)
{
struct HvLpBufferList *bufList;
u64 bytesLeft = bufLen;
u64 leftThisPage;
u64 curPtr = virt_to_absolute( (unsigned long) buffer );
u64 retVal;
int npages;
int i;
npages = 0;
while (bytesLeft) {
npages++;
leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;
if (leftThisPage > bytesLeft)
bytesLeft = 0;
else
bytesLeft -= leftThisPage;
curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
}
if (npages == 0)
return 0;
bufList = (struct HvLpBufferList *)
kmalloc(npages * sizeof(struct HvLpBufferList), GFP_ATOMIC);
bytesLeft = bufLen;
curPtr = virt_to_absolute( (unsigned long) buffer );
for(i=0; i<npages; i++) {
bufList[i].addr = curPtr;
leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr;
if (leftThisPage > bytesLeft) {
bufList[i].len = bytesLeft;
bytesLeft = 0;
} else {
bufList[i].len = leftThisPage;
bytesLeft -= leftThisPage;
}
curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
}
retVal = HvCall3(HvCallBaseReadLogBuffer, lpIndex,
virt_to_absolute((unsigned long)bufList), bufLen);
kfree(bufList);
return (int)retVal; void HvCall_writeLogBuffer(const void *buffer, u64 len)
}
/*=====================================================================
*/
void HvCall_writeLogBuffer(const void *buffer, u64 bufLen)
{ {
struct HvLpBufferList bufList; struct HvLpBufferList hv_buf;
u64 bytesLeft = bufLen; u64 left_this_page;
u64 leftThisPage; u64 cur = virt_to_absolute((unsigned long)buffer);
u64 curPtr = virt_to_absolute((unsigned long) buffer);
while (len) {
while (bytesLeft) { hv_buf.addr = cur;
bufList.addr = curPtr; left_this_page = ((cur & PAGE_MASK) + PAGE_SIZE) - cur;
if (left_this_page > len)
leftThisPage = ((curPtr & PAGE_MASK) + PAGE_SIZE) - curPtr; left_this_page = len;
hv_buf.len = left_this_page;
if (leftThisPage > bytesLeft) { len -= left_this_page;
bufList.len = bytesLeft;
bytesLeft = 0;
} else {
bufList.len = leftThisPage;
bytesLeft -= leftThisPage;
}
HvCall2(HvCallBaseWriteLogBuffer, HvCall2(HvCallBaseWriteLogBuffer,
virt_to_absolute((unsigned long) &bufList), virt_to_absolute((unsigned long)&hv_buf),
bufList.len); left_this_page);
cur = (cur & PAGE_MASK) + PAGE_SIZE;
curPtr = (curPtr & PAGE_MASK) + PAGE_SIZE;
} }
} }
...@@ -147,16 +147,13 @@ unsigned ItLpQueue_process( struct ItLpQueue * lpQueue, struct pt_regs *regs ) ...@@ -147,16 +147,13 @@ unsigned ItLpQueue_process( struct ItLpQueue * lpQueue, struct pt_regs *regs )
printk(KERN_INFO "Unexpected Lp Event type=%d\n", nextLpEvent->xType ); printk(KERN_INFO "Unexpected Lp Event type=%d\n", nextLpEvent->xType );
ItLpQueue_clearValid( nextLpEvent ); ItLpQueue_clearValid( nextLpEvent );
} } else if ( lpQueue->xPlicOverflowIntPending )
else /* No more valid events /*
* If overflow events are pending * No more valid events. If overflow events are
* process them * pending process them
*/ */
if ( lpQueue->xPlicOverflowIntPending ) { HvCallEvent_getOverflowLpEvents( lpQueue->xIndex);
HvCallEvent_getOverflowLpEvents( else
lpQueue->xIndex);
}
else /* If nothing left then we are done */
break; break;
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* This module handles PCI interrupt events sent by the iSeries Hypervisor. * This module handles PCI interrupt events sent by the iSeries Hypervisor.
*/ */
#include <linux/config.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/threads.h> #include <linux/threads.h>
...@@ -70,40 +70,52 @@ struct XmPciLpEvent { ...@@ -70,40 +70,52 @@ struct XmPciLpEvent {
}; };
static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm); static void intReceived(struct XmPciLpEvent *eventParm,
struct pt_regs *regsParm);
static void XmPciLpEvent_handler( struct HvLpEvent* eventParm, struct pt_regs* regsParm) static void XmPciLpEvent_handler(struct HvLpEvent *eventParm,
struct pt_regs *regsParm)
{ {
//PPCDBG(PPCDBG_BUSWALK,"XmPciLpEvent_handler, type 0x%x\n",eventParm->xType ); #ifdef CONFIG_PCI
#if 0
PPCDBG(PPCDBG_BUSWALK, "XmPciLpEvent_handler, type 0x%x\n",
eventParm->xType);
#endif
++Pci_Event_Count; ++Pci_Event_Count;
if (eventParm && eventParm->xType == HvLpEvent_Type_PciIo) { if (eventParm && (eventParm->xType == HvLpEvent_Type_PciIo)) {
switch( eventParm->xFlags.xFunction ) { switch (eventParm->xFlags.xFunction) {
case HvLpEvent_Function_Int: case HvLpEvent_Function_Int:
intReceived( (struct XmPciLpEvent*)eventParm, regsParm ); intReceived((struct XmPciLpEvent *)eventParm, regsParm);
break; break;
case HvLpEvent_Function_Ack: case HvLpEvent_Function_Ack:
printk(KERN_ERR "XmPciLpEvent.c: unexpected ack received\n"); printk(KERN_ERR
"XmPciLpEvent.c: unexpected ack received\n");
break; break;
default: default:
printk(KERN_ERR "XmPciLpEvent.c: unexpected event function %d\n",(int)eventParm->xFlags.xFunction); printk(KERN_ERR
"XmPciLpEvent.c: unexpected event function %d\n",
(int)eventParm->xFlags.xFunction);
break; break;
} }
} } else if (eventParm)
else if (eventParm) { printk(KERN_ERR
printk(KERN_ERR "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",(int)eventParm->xType); "XmPciLpEvent.c: Unrecognized PCI event type 0x%x\n",
} (int)eventParm->xType);
else { else
printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n"); printk(KERN_ERR "XmPciLpEvent.c: NULL event received\n");
} #endif
} }
static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm) static void intReceived(struct XmPciLpEvent *eventParm,
struct pt_regs *regsParm)
{ {
int irq; int irq;
++Pci_Interrupt_Count; ++Pci_Interrupt_Count;
//PPCDBG(PPCDBG_BUSWALK,"PCI: XmPciLpEvent.c: intReceived\n"); #if 0
PPCDBG(PPCDBG_BUSWALK, "PCI: XmPciLpEvent.c: intReceived\n");
#endif
switch (eventParm->hvLpEvent.xSubtype) { switch (eventParm->hvLpEvent.xSubtype) {
case XmPciLpEvent_SlotInterrupt: case XmPciLpEvent_SlotInterrupt:
...@@ -116,28 +128,40 @@ static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm ...@@ -116,28 +128,40 @@ static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm
break; break;
/* Ignore error recovery events for now */ /* Ignore error recovery events for now */
case XmPciLpEvent_BusCreated: case XmPciLpEvent_BusCreated:
printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n", eventParm->eventData.busCreated.busNumber); printk(KERN_INFO "XmPciLpEvent.c: system bus %d created\n",
eventParm->eventData.busCreated.busNumber);
break; break;
case XmPciLpEvent_BusError: case XmPciLpEvent_BusError:
case XmPciLpEvent_BusFailed: case XmPciLpEvent_BusFailed:
printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n", eventParm->eventData.busFailed.busNumber); printk(KERN_INFO "XmPciLpEvent.c: system bus %d failed\n",
eventParm->eventData.busFailed.busNumber);
break; break;
case XmPciLpEvent_BusRecovered: case XmPciLpEvent_BusRecovered:
case XmPciLpEvent_UnQuiesceBus: case XmPciLpEvent_UnQuiesceBus:
printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n", eventParm->eventData.busRecovered.busNumber); printk(KERN_INFO "XmPciLpEvent.c: system bus %d recovered\n",
eventParm->eventData.busRecovered.busNumber);
break; break;
case XmPciLpEvent_NodeFailed: case XmPciLpEvent_NodeFailed:
case XmPciLpEvent_BridgeError: case XmPciLpEvent_BridgeError:
printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n", eventParm->eventData.nodeFailed.busNumber, eventParm->eventData.nodeFailed.subBusNumber, eventParm->eventData.nodeFailed.deviceId); printk(KERN_INFO
"XmPciLpEvent.c: multi-adapter bridge %d/%d/%d failed\n",
eventParm->eventData.nodeFailed.busNumber,
eventParm->eventData.nodeFailed.subBusNumber,
eventParm->eventData.nodeFailed.deviceId);
break; break;
case XmPciLpEvent_NodeRecovered: case XmPciLpEvent_NodeRecovered:
printk(KERN_INFO "XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n", eventParm->eventData.nodeRecovered.busNumber, eventParm->eventData.nodeRecovered.subBusNumber, eventParm->eventData.nodeRecovered.deviceId); printk(KERN_INFO
"XmPciLpEvent.c: multi-adapter bridge %d/%d/%d recovered\n",
eventParm->eventData.nodeRecovered.busNumber,
eventParm->eventData.nodeRecovered.subBusNumber,
eventParm->eventData.nodeRecovered.deviceId);
break; break;
default: default:
printk(KERN_ERR "XmPciLpEvent.c: unrecognized event subtype 0x%x\n", printk(KERN_ERR
"XmPciLpEvent.c: unrecognized event subtype 0x%x\n",
eventParm->hvLpEvent.xSubtype); eventParm->hvLpEvent.xSubtype);
break; break;
}; }
} }
...@@ -145,18 +169,22 @@ static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm ...@@ -145,18 +169,22 @@ static void intReceived(struct XmPciLpEvent* eventParm, struct pt_regs* regsParm
int XmPciLpEvent_init() int XmPciLpEvent_init()
{ {
int xRc; int xRc;
PPCDBG(PPCDBG_BUSWALK,"XmPciLpEvent_init, Register Event type 0x%04X\n",HvLpEvent_Type_PciIo);
xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo, &XmPciLpEvent_handler); PPCDBG(PPCDBG_BUSWALK,
"XmPciLpEvent_init, Register Event type 0x%04X\n",
HvLpEvent_Type_PciIo);
xRc = HvLpEvent_registerHandler(HvLpEvent_Type_PciIo,
&XmPciLpEvent_handler);
if (xRc == 0) { if (xRc == 0) {
xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0); xRc = HvLpEvent_openPath(HvLpEvent_Type_PciIo, 0);
if (xRc != 0) { if (xRc != 0)
printk(KERN_ERR "XmPciLpEvent.c: open event path failed with rc 0x%x\n", xRc); printk(KERN_ERR
} "XmPciLpEvent.c: open event path failed with rc 0x%x\n",
} xRc);
else { } else
printk(KERN_ERR "XmPciLpEvent.c: register handler failed with rc 0x%x\n", xRc); printk(KERN_ERR
} "XmPciLpEvent.c: register handler failed with rc 0x%x\n",
xRc);
return xRc; return xRc;
} }
...@@ -38,127 +38,133 @@ ...@@ -38,127 +38,133 @@
#include "iSeries_IoMmTable.h" #include "iSeries_IoMmTable.h"
#include "pci.h" #include "pci.h"
/*******************************************************************/ /*
/* Table defines */ * Table defines
/* Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space. */ * Each Entry size is 4 MB * 1024 Entries = 4GB I/O address space.
/*******************************************************************/ */
#define Max_Entries 1024 #define Max_Entries 1024
unsigned long iSeries_IoMmTable_Entry_Size = 0x0000000000400000; unsigned long iSeries_IoMmTable_Entry_Size = 0x0000000000400000;
unsigned long iSeries_Base_Io_Memory = 0xE000000000000000; unsigned long iSeries_Base_Io_Memory = 0xE000000000000000;
unsigned long iSeries_Max_Io_Memory = 0xE000000000000000; unsigned long iSeries_Max_Io_Memory = 0xE000000000000000;
static long iSeries_CurrentIndex = 0; static long iSeries_CurrentIndex = 0;
/*******************************************************************/ /*
/* Lookup Tables. */ * Lookup Tables.
/*******************************************************************/ */
struct iSeries_Device_Node** iSeries_IoMmTable; struct iSeries_Device_Node **iSeries_IoMmTable;
u8* iSeries_IoBarTable; u8 *iSeries_IoBarTable;
/*******************************************************************/ /*
/* Static and Global variables */ * Static and Global variables
/*******************************************************************/ */
static char* iSeriesPciIoText = "iSeries PCI I/O"; static char *iSeriesPciIoText = "iSeries PCI I/O";
static spinlock_t iSeriesIoMmTableLock = SPIN_LOCK_UNLOCKED; static spinlock_t iSeriesIoMmTableLock = SPIN_LOCK_UNLOCKED;
/*******************************************************************/ /*
/* iSeries_IoMmTable_Initialize */ * iSeries_IoMmTable_Initialize
/*******************************************************************/ *
/* Allocates and initalizes the Address Translation Table and Bar */ * Allocates and initalizes the Address Translation Table and Bar
/* Tables to get them ready for use. Must be called before any */ * Tables to get them ready for use. Must be called before any
/* I/O space is handed out to the device BARs. */ * I/O space is handed out to the device BARs.
/* A follow up method,iSeries_IoMmTable_Status can be called to */ * A follow up method,iSeries_IoMmTable_Status can be called to
/* adjust the table after the device BARs have been assiged to */ * adjust the table after the device BARs have been assiged to
/* resize the table. */ * resize the table.
/*******************************************************************/ */
void iSeries_IoMmTable_Initialize(void) void iSeries_IoMmTable_Initialize(void)
{ {
spin_lock(&iSeriesIoMmTableLock); spin_lock(&iSeriesIoMmTableLock);
iSeries_IoMmTable = kmalloc(sizeof(void*)*Max_Entries,GFP_KERNEL); iSeries_IoMmTable = kmalloc(sizeof(void *) * Max_Entries, GFP_KERNEL);
iSeries_IoBarTable = kmalloc(sizeof(u8)*Max_Entries, GFP_KERNEL); iSeries_IoBarTable = kmalloc(sizeof(u8) * Max_Entries, GFP_KERNEL);
spin_unlock(&iSeriesIoMmTableLock); spin_unlock(&iSeriesIoMmTableLock);
PCIFR("IoMmTable Initialized 0x%p", iSeries_IoMmTable); PCIFR("IoMmTable Initialized 0x%p", iSeries_IoMmTable);
if(iSeries_IoMmTable == NULL || iSeries_IoBarTable == NULL) { if ((iSeries_IoMmTable == NULL) || (iSeries_IoBarTable == NULL))
panic("PCI: I/O tables allocation failed.\n"); panic("PCI: I/O tables allocation failed.\n");
}
} }
/*******************************************************************/ /*
/* iSeries_IoMmTable_AllocateEntry */ * iSeries_IoMmTable_AllocateEntry
/*******************************************************************/ *
/* Adds pci_dev entry in address translation table */ * Adds pci_dev entry in address translation table
/*******************************************************************/ *
/* - Allocates the number of entries required in table base on BAR */ * - Allocates the number of entries required in table base on BAR
/* size. */ * size.
/* - Allocates starting at iSeries_Base_Io_Memory and increases. */ * - Allocates starting at iSeries_Base_Io_Memory and increases.
/* - The size is round up to be a multiple of entry size. */ * - The size is round up to be a multiple of entry size.
/* - CurrentIndex is incremented to keep track of the last entry. */ * - CurrentIndex is incremented to keep track of the last entry.
/* - Builds the resource entry for allocated BARs. */ * - Builds the resource entry for allocated BARs.
/*******************************************************************/ */
static void iSeries_IoMmTable_AllocateEntry(struct pci_dev* PciDev, int BarNumber) static void iSeries_IoMmTable_AllocateEntry(struct pci_dev *PciDev,
int BarNumber)
{ {
struct resource* BarResource = &PciDev->resource[BarNumber]; struct resource *BarResource = &PciDev->resource[BarNumber];
long BarSize = pci_resource_len(PciDev,BarNumber); long BarSize = pci_resource_len(PciDev, BarNumber);
/***********************************************************/
/* No space to allocate, quick exit, skip Allocation. */ /*
/***********************************************************/ * No space to allocate, quick exit, skip Allocation.
if(BarSize == 0) return; */
/***********************************************************/ if (BarSize == 0)
/* Set Resource values. */ return;
/***********************************************************/ /*
* Set Resource values.
*/
spin_lock(&iSeriesIoMmTableLock); spin_lock(&iSeriesIoMmTableLock);
BarResource->name = iSeriesPciIoText; BarResource->name = iSeriesPciIoText;
BarResource->start = iSeries_IoMmTable_Entry_Size*iSeries_CurrentIndex; BarResource->start =
BarResource->start+= iSeries_Base_Io_Memory; iSeries_IoMmTable_Entry_Size * iSeries_CurrentIndex;
BarResource->start += iSeries_Base_Io_Memory;
BarResource->end = BarResource->start+BarSize-1; BarResource->end = BarResource->start+BarSize-1;
/***********************************************************/ /*
/* Allocate the number of table entries needed for BAR. */ * Allocate the number of table entries needed for BAR.
/***********************************************************/ */
while (BarSize > 0 ) { while (BarSize > 0 ) {
*(iSeries_IoMmTable +iSeries_CurrentIndex) = (struct iSeries_Device_Node*)PciDev->sysdata; *(iSeries_IoMmTable + iSeries_CurrentIndex) =
*(iSeries_IoBarTable+iSeries_CurrentIndex) = BarNumber; (struct iSeries_Device_Node *)PciDev->sysdata;
*(iSeries_IoBarTable + iSeries_CurrentIndex) = BarNumber;
BarSize -= iSeries_IoMmTable_Entry_Size; BarSize -= iSeries_IoMmTable_Entry_Size;
++iSeries_CurrentIndex; ++iSeries_CurrentIndex;
} }
iSeries_Max_Io_Memory = (iSeries_IoMmTable_Entry_Size*iSeries_CurrentIndex)+iSeries_Base_Io_Memory; iSeries_Max_Io_Memory = iSeries_Base_Io_Memory +
(iSeries_IoMmTable_Entry_Size * iSeries_CurrentIndex);
spin_unlock(&iSeriesIoMmTableLock); spin_unlock(&iSeriesIoMmTableLock);
} }
/*******************************************************************/ /*
/* iSeries_allocateDeviceBars */ * iSeries_allocateDeviceBars
/*******************************************************************/ *
/* - Allocates ALL pci_dev BAR's and updates the resources with the*/ * - Allocates ALL pci_dev BAR's and updates the resources with the
/* BAR value. BARS with zero length will have the resources */ * BAR value. BARS with zero length will have the resources
/* The HvCallPci_getBarParms is used to get the size of the BAR */ * The HvCallPci_getBarParms is used to get the size of the BAR
/* space. It calls iSeries_IoMmTable_AllocateEntry to allocate */ * space. It calls iSeries_IoMmTable_AllocateEntry to allocate
/* each entry. */ * each entry.
/* - Loops through The Bar resources(0 - 5) including the ROM */ * - Loops through The Bar resources(0 - 5) including the ROM
/* is resource(6). */ * is resource(6).
/*******************************************************************/ */
void iSeries_allocateDeviceBars(struct pci_dev* PciDev) void iSeries_allocateDeviceBars(struct pci_dev *PciDev)
{ {
struct resource* BarResource; struct resource *BarResource;
int BarNumber; int BarNumber;
for(BarNumber = 0; BarNumber <= PCI_ROM_RESOURCE; ++BarNumber) {
for (BarNumber = 0; BarNumber <= PCI_ROM_RESOURCE; ++BarNumber) {
BarResource = &PciDev->resource[BarNumber]; BarResource = &PciDev->resource[BarNumber];
iSeries_IoMmTable_AllocateEntry(PciDev, BarNumber); iSeries_IoMmTable_AllocateEntry(PciDev, BarNumber);
} }
} }
/************************************************************************/ /*
/* Translates the IoAddress to the device that is mapped to IoSpace. */ * Translates the IoAddress to the device that is mapped to IoSpace.
/* This code is inlined, see the iSeries_pci.c file for the replacement.*/ * This code is inlined, see the iSeries_pci.c file for the replacement.
/************************************************************************/ */
struct iSeries_Device_Node* iSeries_xlateIoMmAddress(void* IoAddress) struct iSeries_Device_Node *iSeries_xlateIoMmAddress(void *IoAddress)
{ {
return NULL; return NULL;
} }
/************************************************************************ /*
* Status hook for IoMmTable * Status hook for IoMmTable
************************************************************************/ */
void iSeries_IoMmTable_Status(void) void iSeries_IoMmTable_Status(void)
{ {
PCIFR("IoMmTable......: 0x%p",iSeries_IoMmTable); PCIFR("IoMmTable......: 0x%p", iSeries_IoMmTable);
PCIFR("IoMmTable Range: 0x%p to 0x%p",iSeries_Base_Io_Memory,iSeries_Max_Io_Memory); PCIFR("IoMmTable Range: 0x%p to 0x%p", iSeries_Base_Io_Memory,
return; iSeries_Max_Io_Memory);
} }
...@@ -31,55 +31,55 @@ ...@@ -31,55 +31,55 @@
struct pci_dev; struct pci_dev;
struct iSeries_Device_Node; struct iSeries_Device_Node;
extern struct iSeries_Device_Node** iSeries_IoMmTable; extern struct iSeries_Device_Node **iSeries_IoMmTable;
extern u8* iSeries_IoBarTable; extern u8 *iSeries_IoBarTable;
extern unsigned long iSeries_Base_Io_Memory; extern unsigned long iSeries_Base_Io_Memory;
extern unsigned long iSeries_Max_Io_Memory; extern unsigned long iSeries_Max_Io_Memory;
extern unsigned long iSeries_Base_Io_Memory; extern unsigned long iSeries_Base_Io_Memory;
extern unsigned long iSeries_IoMmTable_Entry_Size; extern unsigned long iSeries_IoMmTable_Entry_Size;
/************************************************************************/ /*
/* iSeries_IoMmTable_Initialize */ * iSeries_IoMmTable_Initialize
/************************************************************************/ *
/* - Initalizes the Address Translation Table and get it ready for use. */ * - Initalizes the Address Translation Table and get it ready for use.
/* Must be called before any client calls any of the other methods. */ * Must be called before any client calls any of the other methods.
/* */ *
/* Parameters: None. */ * Parameters: None.
/* */ *
/* Return: None. */ * Return: None.
/************************************************************************/ */
extern void iSeries_IoMmTable_Initialize(void); extern void iSeries_IoMmTable_Initialize(void);
extern void iSeries_IoMmTable_Status(void); extern void iSeries_IoMmTable_Status(void);
/************************************************************************/ /*
/* iSeries_allocateDeviceBars */ * iSeries_allocateDeviceBars
/************************************************************************/ *
/* - Allocates ALL pci_dev BAR's and updates the resources with the BAR */ * - Allocates ALL pci_dev BAR's and updates the resources with the BAR
/* value. BARS with zero length will not have the resources. The */ * value. BARS with zero length will not have the resources. The
/* HvCallPci_getBarParms is used to get the size of the BAR space. */ * HvCallPci_getBarParms is used to get the size of the BAR space.
/* It calls iSeries_IoMmTable_AllocateEntry to allocate each entry. */ * It calls iSeries_IoMmTable_AllocateEntry to allocate each entry.
/* */ *
/* Parameters: */ * Parameters:
/* pci_dev = Pointer to pci_dev structure that will be mapped to pseudo */ * pci_dev = Pointer to pci_dev structure that will be mapped to pseudo
/* I/O Address. */ * I/O Address.
/* */ *
/* Return: */ * Return:
/* The pci_dev I/O resources updated with pseudo I/O Addresses. */ * The pci_dev I/O resources updated with pseudo I/O Addresses.
/************************************************************************/ */
extern void iSeries_allocateDeviceBars(struct pci_dev* ); extern void iSeries_allocateDeviceBars(struct pci_dev *);
/************************************************************************/ /*
/* iSeries_xlateIoMmAddress */ * iSeries_xlateIoMmAddress
/************************************************************************/ *
/* - Translates an I/O Memory address to Device Node that has been the */ * - Translates an I/O Memory address to Device Node that has been the
/* allocated the psuedo I/O Address. */ * allocated the psuedo I/O Address.
/* */ *
/* Parameters: */ * Parameters:
/* IoAddress = I/O Memory Address. */ * IoAddress = I/O Memory Address.
/* */ *
/* Return: */ * Return:
/* An iSeries_Device_Node to the device mapped to the I/O address. The*/ * An iSeries_Device_Node to the device mapped to the I/O address. The
/* BarNumber and BarOffset are valid if the Device Node is returned. */ * BarNumber and BarOffset are valid if the Device Node is returned.
/************************************************************************/ */
extern struct iSeries_Device_Node* iSeries_xlateIoMmAddress(void* IoAddress); extern struct iSeries_Device_Node *iSeries_xlateIoMmAddress(void *IoAddress);
#endif /* _ISERIES_IOMMTABLE_H */ #endif /* _ISERIES_IOMMTABLE_H */
...@@ -38,20 +38,20 @@ ...@@ -38,20 +38,20 @@
#include <asm/iSeries/iSeries_pci.h> #include <asm/iSeries/iSeries_pci.h>
#include "pci.h" #include "pci.h"
/************************************************/ /*
/* Size of Bus VPD data */ * Size of Bus VPD data
/************************************************/ */
#define BUS_VPDSIZE 1024 #define BUS_VPDSIZE 1024
/************************************************/ /*
/* Bus Vpd Tags */ * Bus Vpd Tags
/************************************************/ */
#define VpdEndOfDataTag 0x78 #define VpdEndOfDataTag 0x78
#define VpdEndOfAreaTag 0x79 #define VpdEndOfAreaTag 0x79
#define VpdIdStringTag 0x82 #define VpdIdStringTag 0x82
#define VpdVendorAreaTag 0x84 #define VpdVendorAreaTag 0x84
/************************************************/ /*
/* Mfg Area Tags */ * Mfg Area Tags
/************************************************/ */
#define VpdFruFlag 0x4647 // "FG" #define VpdFruFlag 0x4647 // "FG"
#define VpdFruFrameId 0x4649 // "FI" #define VpdFruFrameId 0x4649 // "FI"
#define VpdSlotMapFormat 0x4D46 // "MF" #define VpdSlotMapFormat 0x4D46 // "MF"
...@@ -59,9 +59,9 @@ ...@@ -59,9 +59,9 @@
#define VpdFruSerial 0x534E // "SN" #define VpdFruSerial 0x534E // "SN"
#define VpdSlotMap 0x534D // "SM" #define VpdSlotMap 0x534D // "SM"
/************************************************/ /*
/* Structures of the areas */ * Structures of the areas
/************************************************/ */
struct MfgVpdAreaStruct { struct MfgVpdAreaStruct {
u16 Tag; u16 Tag;
u8 TagLength; u8 TagLength;
...@@ -82,168 +82,172 @@ struct SlotMapStruct { ...@@ -82,168 +82,172 @@ struct SlotMapStruct {
typedef struct SlotMapStruct SlotMap; typedef struct SlotMapStruct SlotMap;
#define SLOT_ENTRY_SIZE 16 #define SLOT_ENTRY_SIZE 16
/**************************************************************** /*
* * * Bus, Card, Board, FrameId, CardLocation.
* Bus, Card, Board, FrameId, CardLocation. * */
****************************************************************/ LocationData* iSeries_GetLocationData(struct pci_dev *PciDev)
LocationData* iSeries_GetLocationData(struct pci_dev* PciDev)
{ {
struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata; struct iSeries_Device_Node *DevNode =
LocationData* LocationPtr = (LocationData*)kmalloc(LOCATION_DATA_SIZE, GFP_KERNEL); (struct iSeries_Device_Node *)PciDev->sysdata;
LocationData *LocationPtr =
(LocationData *)kmalloc(LOCATION_DATA_SIZE, GFP_KERNEL);
if (LocationPtr == NULL) { if (LocationPtr == NULL) {
printk("PCI: LocationData area allocation failed!\n"); printk("PCI: LocationData area allocation failed!\n");
return NULL; return NULL;
} }
memset(LocationPtr,0,LOCATION_DATA_SIZE); memset(LocationPtr, 0, LOCATION_DATA_SIZE);
LocationPtr->Bus = ISERIES_BUS(DevNode); LocationPtr->Bus = ISERIES_BUS(DevNode);
LocationPtr->Board = DevNode->Board; LocationPtr->Board = DevNode->Board;
LocationPtr->FrameId = DevNode->FrameId; LocationPtr->FrameId = DevNode->FrameId;
LocationPtr->Card = PCI_SLOT(DevNode->DevFn); LocationPtr->Card = PCI_SLOT(DevNode->DevFn);
strcpy(&LocationPtr->CardLocation[0],&DevNode->CardLocation[0]); strcpy(&LocationPtr->CardLocation[0], &DevNode->CardLocation[0]);
return LocationPtr; return LocationPtr;
} }
/************************************************************************/ /*
/* Formats the device information. */ * Formats the device information.
/* - Pass in pci_dev* pointer to the device. */ * - Pass in pci_dev* pointer to the device.
/* - Pass in buffer to place the data. Danger here is the buffer must */ * - Pass in buffer to place the data. Danger here is the buffer must
/* be as big as the client says it is. Should be at least 128 bytes.*/ * be as big as the client says it is. Should be at least 128 bytes.
/* Return will the length of the string data put in the buffer. */ * Return will the length of the string data put in the buffer.
/* Format: */ * Format:
/* PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet */ * PCI: Bus 0, Device 26, Vendor 0x12AE Frame 1, Card C10 Ethernet
/* controller */ * controller
/************************************************************************/ */
int iSeries_Device_Information(struct pci_dev* PciDev,char* Buffer, int BufferSize) int iSeries_Device_Information(struct pci_dev *PciDev, char *buffer,
int BufferSize)
{ {
struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata; struct iSeries_Device_Node *DevNode =
char* BufPtr = Buffer; (struct iSeries_Device_Node *)PciDev->sysdata;
int LineLen = 0; int len;
if (DevNode == NULL) { if (DevNode == NULL)
LineLen = sprintf(BufPtr+LineLen, "PCI: iSeries_Device_Information DevNode is NULL"); return sprintf(buffer,
return LineLen; "PCI: iSeries_Device_Information DevNode is NULL");
}
if (BufferSize >= 128) {
LineLen = sprintf(BufPtr+LineLen,"PCI: Bus%3d, Device%3d, Vendor %04X ",
ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn),PciDev->vendor);
LineLen += sprintf(BufPtr+LineLen,"Frame%3d, Card %4s ", DevNode->FrameId,DevNode->CardLocation); if (BufferSize < 128)
return 0;
if (pci_class_name(PciDev->class >> 8) == 0) { len = sprintf(buffer, "PCI: Bus%3d, Device%3d, Vendor %04X ",
LineLen += sprintf(BufPtr+LineLen,"0x%04X ",(int)(PciDev->class >> 8)); ISERIES_BUS(DevNode), PCI_SLOT(PciDev->devfn),
} PciDev->vendor);
else { len += sprintf(buffer + len, "Frame%3d, Card %4s ",
LineLen += sprintf(BufPtr+LineLen,"%s",pci_class_name(PciDev->class >> 8) ); DevNode->FrameId, DevNode->CardLocation);
} #ifdef CONFIG_PCI
} if (pci_class_name(PciDev->class >> 8) == 0)
return LineLen; len += sprintf(buffer + len, "0x%04X ",
(int)(PciDev->class >> 8));
else
len += sprintf(buffer + len, "%s",
pci_class_name(PciDev->class >> 8));
#endif
return len;
} }
/************************************************************************/
/* Build a character string of the device location, Frame 1, Card C10 */ /*
/************************************************************************/ * Build a character string of the device location, Frame 1, Card C10
int device_Location(struct pci_dev* PciDev,char* BufPtr) */
int device_Location(struct pci_dev *PciDev, char *BufPtr)
{ {
struct iSeries_Device_Node* DevNode = (struct iSeries_Device_Node*)PciDev->sysdata; struct iSeries_Device_Node *DevNode =
return sprintf(BufPtr,"PCI: Bus%3d, AgentId%3d, Vendor %04X, Location %s", (struct iSeries_Device_Node *)PciDev->sysdata;
DevNode->DsaAddr.busNumber, return sprintf(BufPtr, "PCI: Bus%3d, AgentId%3d, Vendor %04X, Location %s",
DevNode->AgentId, DevNode->DsaAddr.busNumber, DevNode->AgentId,
DevNode->Vendor, DevNode->Vendor, DevNode->Location);
DevNode->Location);
} }
/*****************************************************************/ /*
/* Parse the Slot Area */ * Parse the Slot Area
/*****************************************************************/ */
void iSeries_Parse_SlotArea(SlotMap* MapPtr,int MapLen, struct iSeries_Device_Node* DevNode) void iSeries_Parse_SlotArea(SlotMap *MapPtr, int MapLen,
struct iSeries_Device_Node *DevNode)
{ {
int SlotMapLen = MapLen; int SlotMapLen = MapLen;
SlotMap* SlotMapPtr = MapPtr; SlotMap *SlotMapPtr = MapPtr;
/*************************************************************/
/* Parse Slot label until we find the one requrested */ /*
/*************************************************************/ * Parse Slot label until we find the one requrested
*/
while (SlotMapLen > 0) { while (SlotMapLen > 0) {
if (SlotMapPtr->AgentId == DevNode->AgentId ) { if (SlotMapPtr->AgentId == DevNode->AgentId ) {
/*******************************************************/ /*
/* If Phb wasn't found, grab the entry first one found.*/ * If Phb wasn't found, grab the entry first one found.
/*******************************************************/ */
if (DevNode->PhbId == 0xff) { if (DevNode->PhbId == 0xff)
DevNode->PhbId = SlotMapPtr->PhbId; DevNode->PhbId = SlotMapPtr->PhbId;
}
/**************************************************/
/* Found it, extract the data. */ /* Found it, extract the data. */
/**************************************************/
if (SlotMapPtr->PhbId == DevNode->PhbId ) { if (SlotMapPtr->PhbId == DevNode->PhbId ) {
memcpy(&DevNode->CardLocation,&SlotMapPtr->CardLocation,3); memcpy(&DevNode->CardLocation,
&SlotMapPtr->CardLocation, 3);
DevNode->CardLocation[3] = 0; DevNode->CardLocation[3] = 0;
break; break;
} }
} }
/*********************************************************/
/* Point to the next Slot */ /* Point to the next Slot */
/*********************************************************/ SlotMapPtr = (SlotMap *)((char *)SlotMapPtr + SLOT_ENTRY_SIZE);
SlotMapPtr = (SlotMap*)((char*)SlotMapPtr+SLOT_ENTRY_SIZE);
SlotMapLen -= SLOT_ENTRY_SIZE; SlotMapLen -= SLOT_ENTRY_SIZE;
} }
} }
/*****************************************************************/ /*
/* Parse the Mfg Area */ * Parse the Mfg Area
/*****************************************************************/ */
static void iSeries_Parse_MfgArea(u8* AreaData,int AreaLen, struct iSeries_Device_Node* DevNode) static void iSeries_Parse_MfgArea(u8 *AreaData, int AreaLen,
struct iSeries_Device_Node *DevNode)
{ {
MfgArea* MfgAreaPtr = (MfgArea*)AreaData; MfgArea *MfgAreaPtr = (MfgArea *)AreaData;
int MfgAreaLen = AreaLen; int MfgAreaLen = AreaLen;
u16 SlotMapFmt = 0; u16 SlotMapFmt = 0;
/*************************************************************/
/* Parse Mfg Data */ /* Parse Mfg Data */
/*************************************************************/
while (MfgAreaLen > 0) { while (MfgAreaLen > 0) {
int MfgTagLen = MfgAreaPtr->TagLength; int MfgTagLen = MfgAreaPtr->TagLength;
/*******************************************************/
/* Frame ID (FI 4649020310 ) */ /* Frame ID (FI 4649020310 ) */
/*******************************************************/ if (MfgAreaPtr->Tag == VpdFruFrameId) /* FI */
if (MfgAreaPtr->Tag == VpdFruFrameId) { /* FI */
DevNode->FrameId = MfgAreaPtr->AreaData1; DevNode->FrameId = MfgAreaPtr->AreaData1;
}
/*******************************************************/
/* Slot Map Format (MF 4D46020004 ) */ /* Slot Map Format (MF 4D46020004 ) */
/*******************************************************/ else if (MfgAreaPtr->Tag == VpdSlotMapFormat) /* MF */
else if (MfgAreaPtr->Tag == VpdSlotMapFormat){ /* MF */ SlotMapFmt = (MfgAreaPtr->AreaData1 * 256)
SlotMapFmt = (MfgAreaPtr->AreaData1*256)+(MfgAreaPtr->AreaData2); + MfgAreaPtr->AreaData2;
}
/*******************************************************/
/* Slot Map (SM 534D90 */ /* Slot Map (SM 534D90 */
/*******************************************************/ else if (MfgAreaPtr->Tag == VpdSlotMap) { /* SM */
else if (MfgAreaPtr->Tag == VpdSlotMap){ /* SM */ SlotMap *SlotMapPtr;
SlotMap* SlotMapPtr;
if (SlotMapFmt == 0x1004) SlotMapPtr = (SlotMap*)((char*)MfgAreaPtr+MFG_ENTRY_SIZE+1); if (SlotMapFmt == 0x1004)
else SlotMapPtr = (SlotMap*)((char*)MfgAreaPtr+MFG_ENTRY_SIZE); SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
iSeries_Parse_SlotArea(SlotMapPtr,MfgTagLen, DevNode); + MFG_ENTRY_SIZE + 1);
else
SlotMapPtr = (SlotMap *)((char *)MfgAreaPtr
+ MFG_ENTRY_SIZE);
iSeries_Parse_SlotArea(SlotMapPtr, MfgTagLen, DevNode);
} }
/*********************************************************/ /*
/* Point to the next Mfg Area */ * Point to the next Mfg Area
/* Use defined size, sizeof give wrong answer */ * Use defined size, sizeof give wrong answer
/*********************************************************/ */
MfgAreaPtr = (MfgArea*)((char*)MfgAreaPtr + MfgTagLen + MFG_ENTRY_SIZE); MfgAreaPtr = (MfgArea *)((char *)MfgAreaPtr + MfgTagLen
+ MFG_ENTRY_SIZE);
MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE); MfgAreaLen -= (MfgTagLen + MFG_ENTRY_SIZE);
} }
} }
/*****************************************************************/ /*
/* Look for "BUS".. Data is not Null terminated. */ * Look for "BUS".. Data is not Null terminated.
/* PHBID of 0xFF indicates PHB was not found in VPD Data. */ * PHBID of 0xFF indicates PHB was not found in VPD Data.
/*****************************************************************/ */
static int iSeries_Parse_PhbId(u8* AreaPtr,int AreaLength) static int iSeries_Parse_PhbId(u8 *AreaPtr, int AreaLength)
{ {
u8* PhbPtr = AreaPtr; u8 *PhbPtr = AreaPtr;
int DataLen = AreaLength; int DataLen = AreaLength;
char PhbId = 0xFF; char PhbId = 0xFF;
while (DataLen > 0) { while (DataLen > 0) {
if (*PhbPtr == 'B' && *(PhbPtr+1) == 'U' && *(PhbPtr+2) == 'S') { if ((*PhbPtr == 'B') && (*(PhbPtr + 1) == 'U')
&& (*(PhbPtr + 2) == 'S')) {
PhbPtr += 3; PhbPtr += 3;
while(*PhbPtr == ' ') ++PhbPtr; while (*PhbPtr == ' ')
++PhbPtr;
PhbId = (*PhbPtr & 0x0F); PhbId = (*PhbPtr & 0x0F);
break; break;
} }
...@@ -253,64 +257,54 @@ static int iSeries_Parse_PhbId(u8* AreaPtr,int AreaLength) ...@@ -253,64 +257,54 @@ static int iSeries_Parse_PhbId(u8* AreaPtr,int AreaLength)
return PhbId; return PhbId;
} }
/****************************************************************/ /*
/* Parse out the VPD Areas */ * Parse out the VPD Areas
/****************************************************************/ */
static void iSeries_Parse_Vpd(u8* VpdData, int VpdDataLen, struct iSeries_Device_Node* DevNode) static void iSeries_Parse_Vpd(u8 *VpdData, int VpdDataLen,
struct iSeries_Device_Node *DevNode)
{ {
u8* TagPtr = VpdData; u8 *TagPtr = VpdData;
int DataLen = VpdDataLen-3; int DataLen = VpdDataLen - 3;
/*************************************************************/
/* Parse the Areas */
/*************************************************************/
while (*TagPtr != VpdEndOfAreaTag && DataLen > 0) {
int AreaLen = *(TagPtr+1) + (*(TagPtr+2)*256);
u8* AreaData = TagPtr+3;
if (*TagPtr == VpdIdStringTag) { while ((*TagPtr != VpdEndOfAreaTag) && (DataLen > 0)) {
DevNode->PhbId = iSeries_Parse_PhbId(AreaData,AreaLen); int AreaLen = *(TagPtr + 1) + (*(TagPtr + 2) * 256);
} u8 *AreaData = TagPtr + 3;
else if (*TagPtr == VpdVendorAreaTag) {
iSeries_Parse_MfgArea(AreaData,AreaLen,DevNode); if (*TagPtr == VpdIdStringTag)
} DevNode->PhbId = iSeries_Parse_PhbId(AreaData, AreaLen);
/********************************************************* else if (*TagPtr == VpdVendorAreaTag)
* Point to next Area. iSeries_Parse_MfgArea(AreaData, AreaLen, DevNode);
*********************************************************/ /* Point to next Area. */
TagPtr = AreaData + AreaLen; TagPtr = AreaData + AreaLen;
DataLen -= AreaLen; DataLen -= AreaLen;
} }
} }
/**************************************************************** void iSeries_Get_Location_Code(struct iSeries_Device_Node *DevNode)
* iSeries_Get_Location_Code(struct iSeries_Device_Node*) *
*
****************************************************************/
void iSeries_Get_Location_Code(struct iSeries_Device_Node* DevNode)
{ {
int BusVpdLen = 0; int BusVpdLen = 0;
u8* BusVpdPtr = (u8*)kmalloc(BUS_VPDSIZE, GFP_KERNEL); u8 *BusVpdPtr = (u8 *)kmalloc(BUS_VPDSIZE, GFP_KERNEL);
if (BusVpdPtr == NULL) { if (BusVpdPtr == NULL) {
printk("PCI: Bus VPD Buffer allocation failure.\n"); printk("PCI: Bus VPD Buffer allocation failure.\n");
return; return;
} }
BusVpdLen = HvCallPci_getBusVpd(ISERIES_BUS(DevNode),REALADDR(BusVpdPtr),BUS_VPDSIZE); BusVpdLen = HvCallPci_getBusVpd(ISERIES_BUS(DevNode),
REALADDR(BusVpdPtr), BUS_VPDSIZE);
if (BusVpdLen == 0) { if (BusVpdLen == 0) {
kfree(BusVpdPtr); kfree(BusVpdPtr);
printk("PCI: Bus VPD Buffer zero length.\n"); printk("PCI: Bus VPD Buffer zero length.\n");
return; return;
} }
//printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); /* printk("PCI: BusVpdPtr: %p, %d\n",BusVpdPtr, BusVpdLen); */
/*************************************************************/
/* Make sure this is what I think it is */ /* Make sure this is what I think it is */
/*************************************************************/ if (*BusVpdPtr != VpdIdStringTag) { /* 0x82 */
if (*BusVpdPtr != VpdIdStringTag) { /*0x82 */
printk("PCI: Bus VPD Buffer missing starting tag.\n"); printk("PCI: Bus VPD Buffer missing starting tag.\n");
kfree(BusVpdPtr); kfree(BusVpdPtr);
return; return;
} }
/***************************************************************/
/***************************************************************/
iSeries_Parse_Vpd(BusVpdPtr,BusVpdLen, DevNode); iSeries_Parse_Vpd(BusVpdPtr,BusVpdLen, DevNode);
sprintf(DevNode->Location,"Frame%3d, Card %-4s",DevNode->FrameId,DevNode->CardLocation); sprintf(DevNode->Location, "Frame%3d, Card %-4s", DevNode->FrameId,
DevNode->CardLocation);
kfree(BusVpdPtr); kfree(BusVpdPtr);
} }
...@@ -42,47 +42,62 @@ ...@@ -42,47 +42,62 @@
#include <asm/iSeries/iSeries_pci.h> #include <asm/iSeries/iSeries_pci.h>
#include "pci.h" #include "pci.h"
/************************************************************************/ /*
/* Interface to toggle the reset line */ * Interface to toggle the reset line
/* Time is in .1 seconds, need for seconds. */ * Time is in .1 seconds, need for seconds.
/************************************************************************/ */
int iSeries_Device_ToggleReset(struct pci_dev* PciDev, int AssertTime, int DelayTime) int iSeries_Device_ToggleReset(struct pci_dev *PciDev, int AssertTime,
int DelayTime)
{ {
unsigned long AssertDelay, WaitDelay; unsigned long AssertDelay, WaitDelay;
struct iSeries_Device_Node* DeviceNode = (struct iSeries_Device_Node*)PciDev->sysdata; struct iSeries_Device_Node *DeviceNode =
(struct iSeries_Device_Node *)PciDev->sysdata;
if (DeviceNode == NULL) { if (DeviceNode == NULL) {
printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",PciDev); printk("PCI: Pci Reset Failed, Device Node not found for pci_dev %p\n",
PciDev);
return -1; return -1;
} }
/******************************************************************** /*
* Set defaults, Assert is .5 second, Wait is 3 seconds. * Set defaults, Assert is .5 second, Wait is 3 seconds.
********************************************************************/ */
if (AssertTime == 0) AssertDelay = ( 5 * HZ)/10; if (AssertTime == 0)
else AssertDelay = (AssertTime*HZ)/10; AssertDelay = (5 * HZ) / 10;
if (WaitDelay == 0) WaitDelay = (30 * HZ)/10; else
else WaitDelay = (DelayTime* HZ)/10; AssertDelay = (AssertTime * HZ) / 10;
if (WaitDelay == 0)
WaitDelay = (30 * HZ) / 10;
else
WaitDelay = (DelayTime * HZ) / 10;
/******************************************************************** /*
* Assert reset * Assert reset
********************************************************************/ */
DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),0x00,DeviceNode->AgentId,1); DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
0x00, DeviceNode->AgentId, 1);
if (DeviceNode->ReturnCode == 0) { if (DeviceNode->ReturnCode == 0) {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(AssertDelay); /* Sleep for the time */ schedule_timeout(AssertDelay); /* Sleep for the time */
DeviceNode->ReturnCode = HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),0x00,DeviceNode->AgentId, 0); DeviceNode->ReturnCode =
HvCallPci_setSlotReset(ISERIES_BUS(DeviceNode),
0x00, DeviceNode->AgentId, 0);
/*************************************************************** /*
* Wait for device to reset * Wait for device to reset
***************************************************************/ */
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(WaitDelay); schedule_timeout(WaitDelay);
} }
if (DeviceNode->ReturnCode == 0) { if (DeviceNode->ReturnCode == 0)
PCIFR("Slot 0x%04X.%02 Reset\n",ISERIES_BUS(DeviceNode),DeviceNode->AgentId ); PCIFR("Slot 0x%04X.%02 Reset\n", ISERIES_BUS(DeviceNode),
} DeviceNode->AgentId);
else { else {
printk("PCI: Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",ISERIES_BUS(DeviceNode),DeviceNode->AgentId,DeviceNode->ReturnCode); printk("PCI: Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
PCIFR( "Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",ISERIES_BUS(DeviceNode),DeviceNode->AgentId,DeviceNode->ReturnCode); ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
DeviceNode->ReturnCode);
PCIFR("Slot 0x%04X.%02X Reset Failed, RCode: %04X\n",
ISERIES_BUS(DeviceNode), DeviceNode->AgentId,
DeviceNode->ReturnCode);
} }
return DeviceNode->ReturnCode; return DeviceNode->ReturnCode;
} }
...@@ -16,29 +16,22 @@ ...@@ -16,29 +16,22 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* Change Activity: */
/* End Change Activity */
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#ifndef _ISERIES_PROC_H #include <linux/init.h>
#include <asm/iSeries/iSeries_proc.h> #include <asm/iSeries/iSeries_proc.h>
#endif
static struct proc_dir_entry *iSeries_proc_root; static struct proc_dir_entry *iSeries_proc_root;
static int iSeries_proc_initializationDone; static int iSeries_proc_initializationDone;
static spinlock_t iSeries_proc_lock; static spinlock_t iSeries_proc_lock;
struct iSeries_proc_registration struct iSeries_proc_registration {
{
struct iSeries_proc_registration *next; struct iSeries_proc_registration *next;
iSeriesProcFunction functionMember; iSeriesProcFunction functionMember;
}; };
struct iSeries_proc_registration preallocated[16]; struct iSeries_proc_registration preallocated[16];
#define MYQUEUETYPE(T) struct MYQueue##T #define MYQUEUETYPE(T) struct MYQueue##T
#define MYQUEUE(T) \ #define MYQUEUE(T) \
MYQUEUETYPE(T) \ MYQUEUETYPE(T) \
...@@ -68,33 +61,33 @@ do { \ ...@@ -68,33 +61,33 @@ do { \
if ((q)->tail == NULL) \ if ((q)->tail == NULL) \
(q)->head = NULL; \ (q)->head = NULL; \
} while(0) } while(0)
MYQUEUE(iSeries_proc_registration); MYQUEUE(iSeries_proc_registration);
typedef MYQUEUETYPE(iSeries_proc_registration) aQueue; typedef MYQUEUETYPE(iSeries_proc_registration) aQueue;
static aQueue iSeries_free;
aQueue iSeries_free; static aQueue iSeries_queued;
aQueue iSeries_queued;
void iSeries_proc_early_init(void) void iSeries_proc_early_init(void)
{ {
int i = 0; int i = 0;
unsigned long flags; unsigned long flags;
iSeries_proc_initializationDone = 0; iSeries_proc_initializationDone = 0;
spin_lock_init(&iSeries_proc_lock); spin_lock_init(&iSeries_proc_lock);
MYQUEUECTOR(&iSeries_free); MYQUEUECTOR(&iSeries_free);
MYQUEUECTOR(&iSeries_queued); MYQUEUECTOR(&iSeries_queued);
spin_lock_irqsave(&iSeries_proc_lock, flags); spin_lock_irqsave(&iSeries_proc_lock, flags);
for (i = 0; i < 16; ++i) { for (i = 0; i < 16; ++i)
MYQUEUEENQ(&iSeries_free, preallocated+i); MYQUEUEENQ(&iSeries_free, preallocated + i);
}
spin_unlock_irqrestore(&iSeries_proc_lock, flags); spin_unlock_irqrestore(&iSeries_proc_lock, flags);
} }
void iSeries_proc_create(void) static int iSeries_proc_create(void)
{ {
unsigned long flags; unsigned long flags;
struct iSeries_proc_registration *reg = NULL; struct iSeries_proc_registration *reg;
printk("iSeries_proc: Creating /proc/iSeries\n"); printk("iSeries_proc: Creating /proc/iSeries\n");
...@@ -112,31 +105,27 @@ void iSeries_proc_create(void) ...@@ -112,31 +105,27 @@ void iSeries_proc_create(void)
iSeries_proc_initializationDone = 1; iSeries_proc_initializationDone = 1;
out: out:
spin_unlock_irqrestore(&iSeries_proc_lock, flags); spin_unlock_irqrestore(&iSeries_proc_lock, flags);
return 0;
} }
arch_initcall(iSeries_proc_create);
void iSeries_proc_callback(iSeriesProcFunction initFunction) void iSeries_proc_callback(iSeriesProcFunction initFunction)
{ {
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&iSeries_proc_lock, flags);
if (iSeries_proc_initializationDone) { spin_lock_irqsave(&iSeries_proc_lock, flags);
if (iSeries_proc_initializationDone)
(*initFunction)(iSeries_proc_root); (*initFunction)(iSeries_proc_root);
} else { else {
struct iSeries_proc_registration *reg = NULL; struct iSeries_proc_registration *reg = NULL;
MYQUEUEDEQ(&iSeries_free, reg); MYQUEUEDEQ(&iSeries_free, reg);
if (reg != NULL) { if (reg != NULL) {
/* printk("Registering %p in reg %p\n", initFunction, reg); */
reg->functionMember = initFunction; reg->functionMember = initFunction;
MYQUEUEENQ(&iSeries_queued, reg); MYQUEUEENQ(&iSeries_queued, reg);
} else { } else
printk("Couldn't get a queue entry\n"); printk("Couldn't get a queue entry\n");
} }
}
spin_unlock_irqrestore(&iSeries_proc_lock, flags); spin_unlock_irqrestore(&iSeries_proc_lock, flags);
} }
...@@ -16,22 +16,15 @@ ...@@ -16,22 +16,15 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* Change Activity: */
/* End Change Activity */
#ifndef _ISERIES_PROC_H #ifndef _ISERIES_PROC_H
#define _ISERIES_PROC_H #define _ISERIES_PROC_H
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
extern void iSeries_proc_early_init(void); extern void iSeries_proc_early_init(void);
extern void iSeries_proc_create(void);
typedef void (*iSeriesProcFunction)(struct proc_dir_entry *iSeries_proc); typedef void (*iSeriesProcFunction)(struct proc_dir_entry *iSeries_proc);
extern void iSeries_proc_callback(iSeriesProcFunction initFunction); extern void iSeries_proc_callback(iSeriesProcFunction initFunction);
#endif /* _iSeries_PROC_H */ #endif /* _iSeries_PROC_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment