diff options
author | Dean Luick <dean.luick@intel.com> | 2016-09-30 07:41:34 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2016-10-02 08:42:19 -0400 |
commit | e2113752b783e387f9cb0d8b9d928c6f9fce08b3 (patch) | |
tree | 6ccea4f92c6b8a88d5160e10422a63f7466b6eeb | |
parent | c642cc070b4934cd4718e63aa46e140468bc6a60 (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.c | 103 | ||||
-rw-r--r-- | drivers/infiniband/hw/hfi1/eprom.h | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/hfi1/file_ops.c | 1 |
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 | */ | ||
88 | static 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 | */ | ||
101 | static 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 | ||
48 | struct hfi1_cmd; | ||
49 | struct hfi1_devdata; | 48 | struct hfi1_devdata; |
50 | 49 | ||
51 | int eprom_init(struct hfi1_devdata *dd); | 50 | int eprom_init(struct hfi1_devdata *dd); |
52 | int 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 | ||