Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c9c2877d authored by Helge Deller's avatar Helge Deller
Browse files

parisc: Add Page Deallocation Table (PDT) support



The firmare in most parisc machines maintains a Page Deallocation Table (PDT)
which holds a list of physical memory addresses where hardware detected memory
errors (single bit and double bit errors).

This patch adds the missing PDC firmware calls and the logic to read the PDT
from firmware, report all current PDT entries and exclude the reported bad
memory from being used by Linux.

Signed-off-by: default avatarHelge Deller <deller@gmx.de>
parent c8c37359
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -6,6 +6,8 @@
#if !defined(__ASSEMBLY__)

extern int pdc_type;
extern unsigned long parisc_cell_num; /* cell number the CPU runs on (PAT) */
extern unsigned long parisc_cell_loc; /* cell location of CPU (PAT)	   */

/* Values for pdc_type */
#define PDC_TYPE_ILLEGAL	-1
@@ -143,6 +145,18 @@ struct pdc_btlb_info { /* PDC_BLOCK_TLB, return of PDC_BTLB_INFO */

#endif /* !CONFIG_PA20 */

struct pdc_mem_retinfo { /* PDC_MEM/PDC_MEM_MEMINFO (return info) */
	unsigned long pdt_size;
	unsigned long pdt_entries;
	unsigned long pdt_status;
	unsigned long first_dbe_loc;
	unsigned long good_mem;
};

struct pdc_mem_read_pdt { /* PDC_MEM/PDC_MEM_READ_PDT (return info) */
	unsigned long pdt_entries;
};

#ifdef CONFIG_64BIT
struct pdc_memory_table_raddr { /* PDC_MEM/PDC_MEM_TABLE (return info) */
	unsigned long entries_returned;
@@ -301,6 +315,10 @@ int pdc_get_initiator(struct hardware_path *, struct pdc_initiator *);
int pdc_tod_read(struct pdc_tod *tod);
int pdc_tod_set(unsigned long sec, unsigned long usec);

void pdc_pdt_init(void);	/* in pdt.c */
int pdc_mem_pdt_info(struct pdc_mem_retinfo *rinfo);
int pdc_mem_pdt_read_entries(struct pdc_mem_read_pdt *rpdt_read,
		unsigned long *pdt_entries_ptr);
#ifdef CONFIG_64BIT
int pdc_mem_mem_table(struct pdc_memory_table_raddr *r_addr,
		struct pdc_memory_table *tbl, unsigned long entries);
+26 −9
Original line number Diff line number Diff line
@@ -147,7 +147,7 @@
#define PDC_PAT_MEM_CELL_CLEAR  	6L /* Clear PDT For Cell           */
#define PDC_PAT_MEM_CELL_READ   	7L /* Read PDT entries For Cell    */
#define PDC_PAT_MEM_CELL_RESET  	8L /* Reset clear bit For Cell     */
#define PDC_PAT_MEM_SETGM	  	9L /* Set Golden Memory value      */
#define PDC_PAT_MEM_SETGM		9L /* Set Good Memory value        */
#define PDC_PAT_MEM_ADD_PAGE		10L /* ADDs a page to the cell      */
#define PDC_PAT_MEM_ADDRESS		11L /* Get Physical Location From   */
                                    		 /* Memory Address               */
@@ -212,6 +212,23 @@ struct pdc_pat_cpu_num {
	unsigned long cpu_loc;
};

struct pdc_pat_mem_retinfo { /* PDC_PAT_MEM/PDC_PAT_MEM_PD_INFO (return info) */
	unsigned int ke;	/* bit 0: memory inside good memory? */
	unsigned int current_pdt_entries:16;
	unsigned int max_pdt_entries:16;
	unsigned long Cs_bitmap;
	unsigned long Ic_bitmap;
	unsigned long good_mem;
	unsigned long first_dbe_loc; /* first location of double bit error */
	unsigned long clear_time; /* last PDT clear time (since Jan 1970) */
};

struct pdc_pat_mem_read_pd_retinfo { /* PDC_PAT_MEM/PDC_PAT_MEM_PD_READ */
	unsigned long actual_count_bytes;
	unsigned long pdt_entries;
};


struct pdc_pat_pd_addr_map_entry {
	unsigned char entry_type;       /* 1 = Memory Descriptor Entry Type */
	unsigned char reserve1[5];
@@ -293,15 +310,15 @@ extern int pdc_pat_cpu_get_number(struct pdc_pat_cpu_num *cpu_info, unsigned lon

extern int pdc_pat_pd_get_addr_map(unsigned long *actual_len, void *mem_addr, unsigned long count, unsigned long offset);


extern int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *val); 
extern int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val); 


/* Flag to indicate this is a PAT box...don't use this unless you
** really have to...it might go away some day.
*/
extern int pdc_pat;     /* arch/parisc/kernel/inventory.c */
extern int pdc_pat_mem_pdt_info(struct pdc_pat_mem_retinfo *rinfo);
extern int pdc_pat_mem_read_cell_pdt(struct pdc_pat_mem_read_pd_retinfo *pret,
		unsigned long *pdt_entries_ptr, unsigned long max_entries);
extern int pdc_pat_mem_read_pd_pdt(struct pdc_pat_mem_read_pd_retinfo *pret,
		unsigned long *pdt_entries_ptr, unsigned long count,
		unsigned long offset);

#endif /* __ASSEMBLY__ */

+3 −0
Original line number Diff line number Diff line
@@ -511,6 +511,9 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,

#define pte_same(A,B)	(pte_val(A) == pte_val(B))

struct seq_file;
extern void arch_report_meminfo(struct seq_file *m);

#endif /* !__ASSEMBLY__ */


+6 −6
Original line number Diff line number Diff line
@@ -131,12 +131,12 @@
#define PDC_TLB_SETUP		1	/* set up miss handling 	*/

#define PDC_MEM		20		/* Manage memory		*/
#define PDC_MEM_MEMINFO		0
#define PDC_MEM_ADD_PAGE	1
#define PDC_MEM_CLEAR_PDT	2
#define PDC_MEM_READ_PDT	3
#define PDC_MEM_RESET_CLEAR	4
#define PDC_MEM_GOODMEM		5
#define PDC_MEM_MEMINFO		0	/* Return PDT info		*/
#define PDC_MEM_ADD_PAGE	1	/* Add page to PDT		*/
#define PDC_MEM_CLEAR_PDT	2	/* Clear PDT			*/
#define PDC_MEM_READ_PDT	3	/* Read PDT entry		*/
#define PDC_MEM_RESET_CLEAR	4	/* Reset PDT clear flag		*/
#define PDC_MEM_GOODMEM		5	/* Set good_mem value		*/
#define PDC_MEM_TABLE		128	/* Non contig mem map (sprockets) */
#define PDC_MEM_RETURN_ADDRESS_TABLE	PDC_MEM_TABLE
#define PDC_MEM_GET_MEMORY_SYSTEM_TABLES_SIZE	131
+1 −1
Original line number Diff line number Diff line
@@ -4,7 +4,7 @@

extra-y			:= head.o vmlinux.lds

obj-y	     	:= cache.o pacache.o setup.o traps.o time.o irq.o \
obj-y	     	:= cache.o pacache.o setup.o pdt.o traps.o time.o irq.o \
		   pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \
		   ptrace.o hardware.o inventory.o drivers.o \
		   signal.o hpmc.o real2.o parisc_ksyms.o unaligned.o \
Loading