Commit 8a5aa00e authored by Helge Deller's avatar Helge Deller
Browse files

parisc: PDT/firmware: Add support to read PDT on older PAT-machines



Older machines with a PAT firmware (e.g. the rp5470) return their Page
Deallocation Table (PDT) info per cell via the PDC_PAT_MEM_PD_INFO PDC call.
This patch adds the necessary structures and wrappers to call firmware.

Signed-off-by: default avatarHelge Deller <deller@gmx.de>
parent 24587380
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -223,6 +223,18 @@ struct pdc_pat_mem_retinfo { /* PDC_PAT_MEM/PDC_PAT_MEM_PD_INFO (return info) */
	unsigned long clear_time; /* last PDT clear time (since Jan 1970) */
};

struct pdc_pat_mem_cell_pdt_retinfo { /* PDC_PAT_MEM/PDC_PAT_MEM_CELL_INFO */
	u64 reserved:32;
	u64 cs:1;		/* clear status: cleared since the last call? */
	u64 current_pdt_entries:15;
	u64 ic:1;		/* interleaving had to be changed ? */
	u64 max_pdt_entries:15;
	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;
@@ -325,6 +337,8 @@ extern int pdc_pat_io_pci_cfg_read(unsigned long pci_addr, int pci_size, u32 *va
extern int pdc_pat_io_pci_cfg_write(unsigned long pci_addr, int pci_size, u32 val); 

extern int pdc_pat_mem_pdt_info(struct pdc_pat_mem_retinfo *rinfo);
extern int pdc_pat_mem_pdt_cell_info(struct pdc_pat_mem_cell_pdt_retinfo *rinfo,
		unsigned long cell);
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,
+39 −8
Original line number Diff line number Diff line
@@ -143,7 +143,7 @@ static void convert_to_wide(unsigned long *addr)
	unsigned int *p = (unsigned int *)addr;

	if (unlikely(parisc_narrow_firmware)) {
		for(i = 31; i >= 0; --i)
		for (i = (NUM_PDC_RESULT-1); i >= 0; --i)
			addr[i] = p[i];
	}
#endif
@@ -979,16 +979,22 @@ int pdc_mem_pdt_read_entries(struct pdc_mem_read_pdt *pret,

	spin_lock_irqsave(&pdc_lock, flags);
	retval = mem_pdc_call(PDC_MEM, PDC_MEM_READ_PDT, __pa(pdc_result),
			__pa(pdc_result2));
			__pa(pdt_entries_ptr));
	if (retval == PDC_OK) {
		convert_to_wide(pdc_result);
		memcpy(pret, pdc_result, sizeof(*pret));
		convert_to_wide(pdc_result2);
		memcpy(pdt_entries_ptr, pdc_result2,
			pret->pdt_entries * sizeof(*pdt_entries_ptr));
	}
	spin_unlock_irqrestore(&pdc_lock, flags);

#ifdef CONFIG_64BIT
	/*
	 * 64-bit kernels should not call this PDT function in narrow mode.
	 * The pdt_entries_ptr array above will now contain 32-bit values
	 */
	if (WARN_ON_ONCE((retval == PDC_OK) && parisc_narrow_firmware))
		return PDC_ERROR;
#endif

	return retval;
}

@@ -1439,6 +1445,29 @@ int pdc_pat_mem_pdt_info(struct pdc_pat_mem_retinfo *rinfo)
	return retval;
}

/**
 * pdc_pat_mem_pdt_cell_info - Retrieve information about page deallocation
 *				table of a cell
 * @rinfo: memory pdt information
 * @cell: cell number
 *
 */
int pdc_pat_mem_pdt_cell_info(struct pdc_pat_mem_cell_pdt_retinfo *rinfo,
		unsigned long cell)
{
	int retval;
	unsigned long flags;

	spin_lock_irqsave(&pdc_lock, flags);
	retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_CELL_INFO,
			__pa(&pdc_result), cell);
	if (retval == PDC_OK)
		memcpy(rinfo, &pdc_result, sizeof(*rinfo));
	spin_unlock_irqrestore(&pdc_lock, flags);

	return retval;
}

/**
 * pdc_pat_mem_read_cell_pdt - Read PDT entries from (old) PAT firmware
 * @pret: array of PDT entries
@@ -1455,14 +1484,14 @@ int pdc_pat_mem_read_cell_pdt(struct pdc_pat_mem_read_pd_retinfo *pret,
	spin_lock_irqsave(&pdc_lock, flags);
	/* PDC_PAT_MEM_CELL_READ is available on early PAT machines only */
	retval = mem_pdc_call(PDC_PAT_MEM, PDC_PAT_MEM_CELL_READ,
			__pa(&pdc_result), parisc_cell_num, __pa(&pdc_result2));
			__pa(&pdc_result), parisc_cell_num,
			__pa(pdt_entries_ptr));

	if (retval == PDC_OK) {
		/* build up return value as for PDC_PAT_MEM_PD_READ */
		entries = min(pdc_result[0], max_entries);
		pret->pdt_entries = entries;
		pret->actual_count_bytes = entries * sizeof(unsigned long);
		memcpy(pdt_entries_ptr, &pdc_result2, pret->actual_count_bytes);
	}

	spin_unlock_irqrestore(&pdc_lock, flags);
@@ -1474,6 +1503,8 @@ int pdc_pat_mem_read_cell_pdt(struct pdc_pat_mem_read_pd_retinfo *pret,
 * pdc_pat_mem_read_pd_pdt - Read PDT entries from (newer) PAT firmware
 * @pret: array of PDT entries
 * @pdt_entries_ptr: ptr to hold number of PDT entries
 * @count: number of bytes to read
 * @offset: offset to start (in bytes)
 *
 */
int pdc_pat_mem_read_pd_pdt(struct pdc_pat_mem_read_pd_retinfo *pret,