aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDean Luick <dean.luick@intel.com>2016-09-30 07:41:34 -0400
committerDoug Ledford <dledford@redhat.com>2016-10-02 08:42:19 -0400
commite2113752b783e387f9cb0d8b9d928c6f9fce08b3 (patch)
tree6ccea4f92c6b8a88d5160e10422a63f7466b6eeb
parentc642cc070b4934cd4718e63aa46e140468bc6a60 (diff)
IB/hfi1: Restore EPROM read ability
Partially revert commit d07903174202 ("IB/hfi1: Remove EPROM functionality from data device"), bringing back the ability to read from the EPROM. This code will be used for driver-only acccess to the EPROM, hence change EPROM read to save to a buffer instead of copy touser. Also allow any offset and remove missed includes and leftover declarations. Reviewed-by: Easwar Hariharan <easwar.hariharan@intel.com> Signed-off-by: Dean Luick <dean.luick@intel.com> Signed-off-by: Dennis Dalessandro <dennis.dalessandro@intel.com> Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r--drivers/infiniband/hw/hfi1/eprom.c103
-rw-r--r--drivers/infiniband/hw/hfi1/eprom.h2
-rw-r--r--drivers/infiniband/hw/hfi1/file_ops.c1
3 files changed, 103 insertions, 3 deletions
diff --git a/drivers/infiniband/hw/hfi1/eprom.c b/drivers/infiniband/hw/hfi1/eprom.c
index 36b77943cbfd..30ecd9481e3a 100644
--- a/drivers/infiniband/hw/hfi1/eprom.c
+++ b/drivers/infiniband/hw/hfi1/eprom.c
@@ -49,7 +49,26 @@
49#include "common.h" 49#include "common.h"
50#include "eprom.h" 50#include "eprom.h"
51 51
52/*
53 * The EPROM is logically divided into three partitions:
54 * partition 0: the first 128K, visible from PCI ROM BAR
55 * partition 1: 4K config file (sector size)
56 * partition 2: the rest
57 */
58#define P0_SIZE (128 * 1024)
59#define P1_SIZE (4 * 1024)
60#define P1_START P0_SIZE
61#define P2_START (P0_SIZE + P1_SIZE)
62
63/* controller page size, in bytes */
64#define EP_PAGE_SIZE 256
65#define EP_PAGE_MASK (EP_PAGE_SIZE - 1)
66#define EP_PAGE_DWORDS (EP_PAGE_SIZE / sizeof(u32))
67
68/* controller commands */
52#define CMD_SHIFT 24 69#define CMD_SHIFT 24
70#define CMD_NOP (0)
71#define CMD_READ_DATA(addr) ((0x03 << CMD_SHIFT) | addr)
53#define CMD_RELEASE_POWERDOWN_NOID ((0xab << CMD_SHIFT)) 72#define CMD_RELEASE_POWERDOWN_NOID ((0xab << CMD_SHIFT))
54 73
55/* controller interface speeds */ 74/* controller interface speeds */
@@ -61,6 +80,90 @@
61 * Double it for safety. 80 * Double it for safety.
62 */ 81 */
63#define EPROM_TIMEOUT 80000 /* ms */ 82#define EPROM_TIMEOUT 80000 /* ms */
83
84/*
85 * Read a 256 byte (64 dword) EPROM page.
86 * All callers have verified the offset is at a page boundary.
87 */
88static void read_page(struct hfi1_devdata *dd, u32 offset, u32 *result)
89{
90 int i;
91
92 write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_READ_DATA(offset));
93 for (i = 0; i < EP_PAGE_DWORDS; i++)
94 result[i] = (u32)read_csr(dd, ASIC_EEP_DATA);
95 write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_NOP); /* close open page */
96}
97
98/*
99 * Read length bytes starting at offset from the start of the EPROM.
100 */
101static int read_length(struct hfi1_devdata *dd, u32 start, u32 len, void *dest)
102{
103 u32 buffer[EP_PAGE_DWORDS];
104 u32 end;
105 u32 start_offset;
106 u32 read_start;
107 u32 bytes;
108
109 if (len == 0)
110 return 0;
111
112 end = start + len;
113
114 /*
115 * Make sure the read range is not outside of the controller read
116 * command address range. Note that '>' is correct below - the end
117 * of the range is OK if it stops at the limit, but no higher.
118 */
119 if (end > (1 << CMD_SHIFT))
120 return -EINVAL;
121
122 /* read the first partial page */
123 start_offset = start & EP_PAGE_MASK;
124 if (start_offset) {
125 /* partial starting page */
126
127 /* align and read the page that contains the start */
128 read_start = start & ~EP_PAGE_MASK;
129 read_page(dd, read_start, buffer);
130
131 /* the rest of the page is available data */
132 bytes = EP_PAGE_SIZE - start_offset;
133
134 if (len <= bytes) {
135 /* end is within this page */
136 memcpy(dest, (u8 *)buffer + start_offset, len);
137 return 0;
138 }
139
140 memcpy(dest, (u8 *)buffer + start_offset, bytes);
141
142 start += bytes;
143 len -= bytes;
144 dest += bytes;
145 }
146 /* start is now page aligned */
147
148 /* read whole pages */
149 while (len >= EP_PAGE_SIZE) {
150 read_page(dd, start, buffer);
151 memcpy(dest, buffer, EP_PAGE_SIZE);
152
153 start += EP_PAGE_SIZE;
154 len -= EP_PAGE_SIZE;
155 dest += EP_PAGE_SIZE;
156 }
157
158 /* read the last partial page */
159 if (len) {
160 read_page(dd, start, buffer);
161 memcpy(dest, buffer, len);
162 }
163
164 return 0;
165}
166
64/* 167/*
65 * Initialize the EPROM handler. 168 * Initialize the EPROM handler.
66 */ 169 */
diff --git a/drivers/infiniband/hw/hfi1/eprom.h b/drivers/infiniband/hw/hfi1/eprom.h
index d41f0b1afb15..b7ac9cee1076 100644
--- a/drivers/infiniband/hw/hfi1/eprom.h
+++ b/drivers/infiniband/hw/hfi1/eprom.h
@@ -45,8 +45,6 @@
45 * 45 *
46 */ 46 */
47 47
48struct hfi1_cmd;
49struct hfi1_devdata; 48struct hfi1_devdata;
50 49
51int eprom_init(struct hfi1_devdata *dd); 50int eprom_init(struct hfi1_devdata *dd);
52int handle_eprom_command(struct file *fp, const struct hfi1_cmd *cmd);
diff --git a/drivers/infiniband/hw/hfi1/file_ops.c b/drivers/infiniband/hw/hfi1/file_ops.c
index 13bb6a5e4d37..677efa0e8cd6 100644
--- a/drivers/infiniband/hw/hfi1/file_ops.c
+++ b/drivers/infiniband/hw/hfi1/file_ops.c
@@ -58,7 +58,6 @@
58#include "trace.h" 58#include "trace.h"
59#include "user_sdma.h" 59#include "user_sdma.h"
60#include "user_exp_rcv.h" 60#include "user_exp_rcv.h"
61#include "eprom.h"
62#include "aspm.h" 61#include "aspm.h"
63#include "mmu_rb.h" 62#include "mmu_rb.h"
64 63