diff options
author | Dean Luick <dean.luick@intel.com> | 2015-11-16 21:59:35 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-12-21 16:45:38 -0500 |
commit | cd371e0959a3f2d5df69d50000750f7eefc94659 (patch) | |
tree | 61d2494139a11d7ab753d04df35ff11f5188556a | |
parent | 5d9157aafb16bed45e3bf167baa16f1fbe1090cd (diff) |
staging/rdma/hfi1: Adjust EPROM partitions, add EPROM commands
Add a new EPROM partition, adjusting partition placement.
Add EPROM range commands as a supserset of the partition
commands. Remove old partition commands.
Enhance EPROM erase, creating a range function and using the
largest erase (sub) commands when possible.
Reviewed-by: Dennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Jubin John <jubin.john@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/rdma/hfi1/eprom.c | 119 | ||||
-rw-r--r-- | drivers/staging/rdma/hfi1/file_ops.c | 18 | ||||
-rw-r--r-- | include/uapi/rdma/hfi/hfi1_user.h | 10 |
3 files changed, 77 insertions, 70 deletions
diff --git a/drivers/staging/rdma/hfi1/eprom.c b/drivers/staging/rdma/hfi1/eprom.c index b61d3ae93ed1..fb620c97f592 100644 --- a/drivers/staging/rdma/hfi1/eprom.c +++ b/drivers/staging/rdma/hfi1/eprom.c | |||
@@ -53,17 +53,26 @@ | |||
53 | #include "eprom.h" | 53 | #include "eprom.h" |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * The EPROM is logically divided into two partitions: | 56 | * The EPROM is logically divided into three partitions: |
57 | * partition 0: the first 128K, visible from PCI ROM BAR | 57 | * partition 0: the first 128K, visible from PCI ROM BAR |
58 | * partition 1: the rest | 58 | * partition 1: 4K config file (sector size) |
59 | * partition 2: the rest | ||
59 | */ | 60 | */ |
60 | #define P0_SIZE (128 * 1024) | 61 | #define P0_SIZE (128 * 1024) |
62 | #define P1_SIZE (4 * 1024) | ||
61 | #define P1_START P0_SIZE | 63 | #define P1_START P0_SIZE |
64 | #define P2_START (P0_SIZE + P1_SIZE) | ||
65 | |||
66 | /* erase sizes supported by the controller */ | ||
67 | #define SIZE_4KB (4 * 1024) | ||
68 | #define MASK_4KB (SIZE_4KB - 1) | ||
62 | 69 | ||
63 | /* largest erase size supported by the controller */ | ||
64 | #define SIZE_32KB (32 * 1024) | 70 | #define SIZE_32KB (32 * 1024) |
65 | #define MASK_32KB (SIZE_32KB - 1) | 71 | #define MASK_32KB (SIZE_32KB - 1) |
66 | 72 | ||
73 | #define SIZE_64KB (64 * 1024) | ||
74 | #define MASK_64KB (SIZE_64KB - 1) | ||
75 | |||
67 | /* controller page size, in bytes */ | 76 | /* controller page size, in bytes */ |
68 | #define EP_PAGE_SIZE 256 | 77 | #define EP_PAGE_SIZE 256 |
69 | #define EEP_PAGE_MASK (EP_PAGE_SIZE - 1) | 78 | #define EEP_PAGE_MASK (EP_PAGE_SIZE - 1) |
@@ -75,10 +84,12 @@ | |||
75 | #define CMD_READ_DATA(addr) ((0x03 << CMD_SHIFT) | addr) | 84 | #define CMD_READ_DATA(addr) ((0x03 << CMD_SHIFT) | addr) |
76 | #define CMD_READ_SR1 ((0x05 << CMD_SHIFT)) | 85 | #define CMD_READ_SR1 ((0x05 << CMD_SHIFT)) |
77 | #define CMD_WRITE_ENABLE ((0x06 << CMD_SHIFT)) | 86 | #define CMD_WRITE_ENABLE ((0x06 << CMD_SHIFT)) |
87 | #define CMD_SECTOR_ERASE_4KB(addr) ((0x20 << CMD_SHIFT) | addr) | ||
78 | #define CMD_SECTOR_ERASE_32KB(addr) ((0x52 << CMD_SHIFT) | addr) | 88 | #define CMD_SECTOR_ERASE_32KB(addr) ((0x52 << CMD_SHIFT) | addr) |
79 | #define CMD_CHIP_ERASE ((0x60 << CMD_SHIFT)) | 89 | #define CMD_CHIP_ERASE ((0x60 << CMD_SHIFT)) |
80 | #define CMD_READ_MANUF_DEV_ID ((0x90 << CMD_SHIFT)) | 90 | #define CMD_READ_MANUF_DEV_ID ((0x90 << CMD_SHIFT)) |
81 | #define CMD_RELEASE_POWERDOWN_NOID ((0xab << CMD_SHIFT)) | 91 | #define CMD_RELEASE_POWERDOWN_NOID ((0xab << CMD_SHIFT)) |
92 | #define CMD_SECTOR_ERASE_64KB(addr) ((0xd8 << CMD_SHIFT) | addr) | ||
82 | 93 | ||
83 | /* controller interface speeds */ | 94 | /* controller interface speeds */ |
84 | #define EP_SPEED_FULL 0x2 /* full speed */ | 95 | #define EP_SPEED_FULL 0x2 /* full speed */ |
@@ -188,28 +199,43 @@ static int erase_chip(struct hfi1_devdata *dd) | |||
188 | } | 199 | } |
189 | 200 | ||
190 | /* | 201 | /* |
191 | * Erase a range using the 32KB erase command. | 202 | * Erase a range. |
192 | */ | 203 | */ |
193 | static int erase_32kb_range(struct hfi1_devdata *dd, u32 start, u32 end) | 204 | static int erase_range(struct hfi1_devdata *dd, u32 start, u32 len) |
194 | { | 205 | { |
206 | u32 end = start + len; | ||
195 | int ret = 0; | 207 | int ret = 0; |
196 | 208 | ||
197 | if (end < start) | 209 | if (end < start) |
198 | return -EINVAL; | 210 | return -EINVAL; |
199 | 211 | ||
200 | if ((start & MASK_32KB) || (end & MASK_32KB)) { | 212 | /* check the end points for the minimum erase */ |
213 | if ((start & MASK_4KB) || (end & MASK_4KB)) { | ||
201 | dd_dev_err(dd, | 214 | dd_dev_err(dd, |
202 | "%s: non-aligned range (0x%x,0x%x) for a 32KB erase\n", | 215 | "%s: non-aligned range (0x%x,0x%x) for a 4KB erase\n", |
203 | __func__, start, end); | 216 | __func__, start, end); |
204 | return -EINVAL; | 217 | return -EINVAL; |
205 | } | 218 | } |
206 | 219 | ||
207 | write_enable(dd); | 220 | write_enable(dd); |
208 | 221 | ||
209 | for (; start < end; start += SIZE_32KB) { | 222 | while (start < end) { |
210 | write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_WRITE_ENABLE); | 223 | write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_WRITE_ENABLE); |
211 | write_csr(dd, ASIC_EEP_ADDR_CMD, | 224 | /* check in order of largest to smallest */ |
212 | CMD_SECTOR_ERASE_32KB(start)); | 225 | if (((start & MASK_64KB) == 0) && (start + SIZE_64KB <= end)) { |
226 | write_csr(dd, ASIC_EEP_ADDR_CMD, | ||
227 | CMD_SECTOR_ERASE_64KB(start)); | ||
228 | start += SIZE_64KB; | ||
229 | } else if (((start & MASK_32KB) == 0) && | ||
230 | (start + SIZE_32KB <= end)) { | ||
231 | write_csr(dd, ASIC_EEP_ADDR_CMD, | ||
232 | CMD_SECTOR_ERASE_32KB(start)); | ||
233 | start += SIZE_32KB; | ||
234 | } else { /* 4KB will work */ | ||
235 | write_csr(dd, ASIC_EEP_ADDR_CMD, | ||
236 | CMD_SECTOR_ERASE_4KB(start)); | ||
237 | start += SIZE_4KB; | ||
238 | } | ||
213 | ret = wait_for_not_busy(dd); | 239 | ret = wait_for_not_busy(dd); |
214 | if (ret) | 240 | if (ret) |
215 | goto done; | 241 | goto done; |
@@ -309,6 +335,18 @@ done: | |||
309 | return ret; | 335 | return ret; |
310 | } | 336 | } |
311 | 337 | ||
338 | /* convert an range composite to a length, in bytes */ | ||
339 | static inline u32 extract_rlen(u32 composite) | ||
340 | { | ||
341 | return (composite & 0xffff) * EP_PAGE_SIZE; | ||
342 | } | ||
343 | |||
344 | /* convert an range composite to a start, in bytes */ | ||
345 | static inline u32 extract_rstart(u32 composite) | ||
346 | { | ||
347 | return (composite >> 16) * EP_PAGE_SIZE; | ||
348 | } | ||
349 | |||
312 | /* | 350 | /* |
313 | * Perform the given operation on the EPROM. Called from user space. The | 351 | * Perform the given operation on the EPROM. Called from user space. The |
314 | * user credentials have already been checked. | 352 | * user credentials have already been checked. |
@@ -319,6 +357,8 @@ int handle_eprom_command(const struct hfi1_cmd *cmd) | |||
319 | { | 357 | { |
320 | struct hfi1_devdata *dd; | 358 | struct hfi1_devdata *dd; |
321 | u32 dev_id; | 359 | u32 dev_id; |
360 | u32 rlen; /* range length */ | ||
361 | u32 rstart; /* range start */ | ||
322 | int ret = 0; | 362 | int ret = 0; |
323 | 363 | ||
324 | /* | 364 | /* |
@@ -364,54 +404,29 @@ int handle_eprom_command(const struct hfi1_cmd *cmd) | |||
364 | sizeof(u32))) | 404 | sizeof(u32))) |
365 | ret = -EFAULT; | 405 | ret = -EFAULT; |
366 | break; | 406 | break; |
407 | |||
367 | case HFI1_CMD_EP_ERASE_CHIP: | 408 | case HFI1_CMD_EP_ERASE_CHIP: |
368 | ret = erase_chip(dd); | 409 | ret = erase_chip(dd); |
369 | break; | 410 | break; |
370 | case HFI1_CMD_EP_ERASE_P0: | 411 | |
371 | if (cmd->len != P0_SIZE) { | 412 | case HFI1_CMD_EP_ERASE_RANGE: |
372 | ret = -ERANGE; | 413 | rlen = extract_rlen(cmd->len); |
373 | break; | 414 | rstart = extract_rstart(cmd->len); |
374 | } | 415 | ret = erase_range(dd, rstart, rlen); |
375 | ret = erase_32kb_range(dd, 0, cmd->len); | ||
376 | break; | ||
377 | case HFI1_CMD_EP_ERASE_P1: | ||
378 | /* check for overflow */ | ||
379 | if (P1_START + cmd->len > ASIC_EEP_ADDR_CMD_EP_ADDR_MASK) { | ||
380 | ret = -ERANGE; | ||
381 | break; | ||
382 | } | ||
383 | ret = erase_32kb_range(dd, P1_START, P1_START + cmd->len); | ||
384 | break; | ||
385 | case HFI1_CMD_EP_READ_P0: | ||
386 | if (cmd->len != P0_SIZE) { | ||
387 | ret = -ERANGE; | ||
388 | break; | ||
389 | } | ||
390 | ret = read_length(dd, 0, cmd->len, cmd->addr); | ||
391 | break; | ||
392 | case HFI1_CMD_EP_READ_P1: | ||
393 | /* check for overflow */ | ||
394 | if (P1_START + cmd->len > ASIC_EEP_ADDR_CMD_EP_ADDR_MASK) { | ||
395 | ret = -ERANGE; | ||
396 | break; | ||
397 | } | ||
398 | ret = read_length(dd, P1_START, cmd->len, cmd->addr); | ||
399 | break; | 416 | break; |
400 | case HFI1_CMD_EP_WRITE_P0: | 417 | |
401 | if (cmd->len > P0_SIZE) { | 418 | case HFI1_CMD_EP_READ_RANGE: |
402 | ret = -ERANGE; | 419 | rlen = extract_rlen(cmd->len); |
403 | break; | 420 | rstart = extract_rstart(cmd->len); |
404 | } | 421 | ret = read_length(dd, rstart, rlen, cmd->addr); |
405 | ret = write_length(dd, 0, cmd->len, cmd->addr); | ||
406 | break; | 422 | break; |
407 | case HFI1_CMD_EP_WRITE_P1: | 423 | |
408 | /* check for overflow */ | 424 | case HFI1_CMD_EP_WRITE_RANGE: |
409 | if (P1_START + cmd->len > ASIC_EEP_ADDR_CMD_EP_ADDR_MASK) { | 425 | rlen = extract_rlen(cmd->len); |
410 | ret = -ERANGE; | 426 | rstart = extract_rstart(cmd->len); |
411 | break; | 427 | ret = write_length(dd, rstart, rlen, cmd->addr); |
412 | } | ||
413 | ret = write_length(dd, P1_START, cmd->len, cmd->addr); | ||
414 | break; | 428 | break; |
429 | |||
415 | default: | 430 | default: |
416 | dd_dev_err(dd, "%s: unexpected command %d\n", | 431 | dd_dev_err(dd, "%s: unexpected command %d\n", |
417 | __func__, cmd->type); | 432 | __func__, cmd->type); |
diff --git a/drivers/staging/rdma/hfi1/file_ops.c b/drivers/staging/rdma/hfi1/file_ops.c index 22037ce984c8..874305f0a925 100644 --- a/drivers/staging/rdma/hfi1/file_ops.c +++ b/drivers/staging/rdma/hfi1/file_ops.c | |||
@@ -234,12 +234,9 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data, | |||
234 | break; | 234 | break; |
235 | case HFI1_CMD_EP_INFO: | 235 | case HFI1_CMD_EP_INFO: |
236 | case HFI1_CMD_EP_ERASE_CHIP: | 236 | case HFI1_CMD_EP_ERASE_CHIP: |
237 | case HFI1_CMD_EP_ERASE_P0: | 237 | case HFI1_CMD_EP_ERASE_RANGE: |
238 | case HFI1_CMD_EP_ERASE_P1: | 238 | case HFI1_CMD_EP_READ_RANGE: |
239 | case HFI1_CMD_EP_READ_P0: | 239 | case HFI1_CMD_EP_WRITE_RANGE: |
240 | case HFI1_CMD_EP_READ_P1: | ||
241 | case HFI1_CMD_EP_WRITE_P0: | ||
242 | case HFI1_CMD_EP_WRITE_P1: | ||
243 | uctxt_required = 0; /* assigned user context not required */ | 240 | uctxt_required = 0; /* assigned user context not required */ |
244 | must_be_root = 1; /* validate user */ | 241 | must_be_root = 1; /* validate user */ |
245 | copy = 0; | 242 | copy = 0; |
@@ -393,12 +390,9 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data, | |||
393 | } | 390 | } |
394 | case HFI1_CMD_EP_INFO: | 391 | case HFI1_CMD_EP_INFO: |
395 | case HFI1_CMD_EP_ERASE_CHIP: | 392 | case HFI1_CMD_EP_ERASE_CHIP: |
396 | case HFI1_CMD_EP_ERASE_P0: | 393 | case HFI1_CMD_EP_ERASE_RANGE: |
397 | case HFI1_CMD_EP_ERASE_P1: | 394 | case HFI1_CMD_EP_READ_RANGE: |
398 | case HFI1_CMD_EP_READ_P0: | 395 | case HFI1_CMD_EP_WRITE_RANGE: |
399 | case HFI1_CMD_EP_READ_P1: | ||
400 | case HFI1_CMD_EP_WRITE_P0: | ||
401 | case HFI1_CMD_EP_WRITE_P1: | ||
402 | ret = handle_eprom_command(&cmd); | 396 | ret = handle_eprom_command(&cmd); |
403 | break; | 397 | break; |
404 | } | 398 | } |
diff --git a/include/uapi/rdma/hfi/hfi1_user.h b/include/uapi/rdma/hfi/hfi1_user.h index a2fc6cbfe414..288694e422fb 100644 --- a/include/uapi/rdma/hfi/hfi1_user.h +++ b/include/uapi/rdma/hfi/hfi1_user.h | |||
@@ -137,12 +137,10 @@ | |||
137 | /* separate EPROM commands from normal PSM commands */ | 137 | /* separate EPROM commands from normal PSM commands */ |
138 | #define HFI1_CMD_EP_INFO 64 /* read EPROM device ID */ | 138 | #define HFI1_CMD_EP_INFO 64 /* read EPROM device ID */ |
139 | #define HFI1_CMD_EP_ERASE_CHIP 65 /* erase whole EPROM */ | 139 | #define HFI1_CMD_EP_ERASE_CHIP 65 /* erase whole EPROM */ |
140 | #define HFI1_CMD_EP_ERASE_P0 66 /* erase EPROM partition 0 */ | 140 | /* range 66-74 no longer used */ |
141 | #define HFI1_CMD_EP_ERASE_P1 67 /* erase EPROM partition 1 */ | 141 | #define HFI1_CMD_EP_ERASE_RANGE 75 /* erase EPROM range */ |
142 | #define HFI1_CMD_EP_READ_P0 68 /* read EPROM partition 0 */ | 142 | #define HFI1_CMD_EP_READ_RANGE 76 /* read EPROM range */ |
143 | #define HFI1_CMD_EP_READ_P1 69 /* read EPROM partition 1 */ | 143 | #define HFI1_CMD_EP_WRITE_RANGE 77 /* write EPROM range */ |
144 | #define HFI1_CMD_EP_WRITE_P0 70 /* write EPROM partition 0 */ | ||
145 | #define HFI1_CMD_EP_WRITE_P1 71 /* write EPROM partition 1 */ | ||
146 | 144 | ||
147 | #define _HFI1_EVENT_FROZEN_BIT 0 | 145 | #define _HFI1_EVENT_FROZEN_BIT 0 |
148 | #define _HFI1_EVENT_LINKDOWN_BIT 1 | 146 | #define _HFI1_EVENT_LINKDOWN_BIT 1 |