Commit cd371e09 authored by Dean Luick's avatar Dean Luick Committed by Greg Kroah-Hartman

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: default avatarDennis Dalessandro <dennis.dalessandro@intel.com>
Signed-off-by: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarJubin John <jubin.john@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 5d9157aa
...@@ -53,17 +53,26 @@ ...@@ -53,17 +53,26 @@
#include "eprom.h" #include "eprom.h"
/* /*
* The EPROM is logically divided into two partitions: * The EPROM is logically divided into three partitions:
* partition 0: the first 128K, visible from PCI ROM BAR * partition 0: the first 128K, visible from PCI ROM BAR
* partition 1: the rest * partition 1: 4K config file (sector size)
* partition 2: the rest
*/ */
#define P0_SIZE (128 * 1024) #define P0_SIZE (128 * 1024)
#define P1_SIZE (4 * 1024)
#define P1_START P0_SIZE #define P1_START P0_SIZE
#define P2_START (P0_SIZE + P1_SIZE)
/* erase sizes supported by the controller */
#define SIZE_4KB (4 * 1024)
#define MASK_4KB (SIZE_4KB - 1)
/* largest erase size supported by the controller */
#define SIZE_32KB (32 * 1024) #define SIZE_32KB (32 * 1024)
#define MASK_32KB (SIZE_32KB - 1) #define MASK_32KB (SIZE_32KB - 1)
#define SIZE_64KB (64 * 1024)
#define MASK_64KB (SIZE_64KB - 1)
/* controller page size, in bytes */ /* controller page size, in bytes */
#define EP_PAGE_SIZE 256 #define EP_PAGE_SIZE 256
#define EEP_PAGE_MASK (EP_PAGE_SIZE - 1) #define EEP_PAGE_MASK (EP_PAGE_SIZE - 1)
...@@ -75,10 +84,12 @@ ...@@ -75,10 +84,12 @@
#define CMD_READ_DATA(addr) ((0x03 << CMD_SHIFT) | addr) #define CMD_READ_DATA(addr) ((0x03 << CMD_SHIFT) | addr)
#define CMD_READ_SR1 ((0x05 << CMD_SHIFT)) #define CMD_READ_SR1 ((0x05 << CMD_SHIFT))
#define CMD_WRITE_ENABLE ((0x06 << CMD_SHIFT)) #define CMD_WRITE_ENABLE ((0x06 << CMD_SHIFT))
#define CMD_SECTOR_ERASE_4KB(addr) ((0x20 << CMD_SHIFT) | addr)
#define CMD_SECTOR_ERASE_32KB(addr) ((0x52 << CMD_SHIFT) | addr) #define CMD_SECTOR_ERASE_32KB(addr) ((0x52 << CMD_SHIFT) | addr)
#define CMD_CHIP_ERASE ((0x60 << CMD_SHIFT)) #define CMD_CHIP_ERASE ((0x60 << CMD_SHIFT))
#define CMD_READ_MANUF_DEV_ID ((0x90 << CMD_SHIFT)) #define CMD_READ_MANUF_DEV_ID ((0x90 << CMD_SHIFT))
#define CMD_RELEASE_POWERDOWN_NOID ((0xab << CMD_SHIFT)) #define CMD_RELEASE_POWERDOWN_NOID ((0xab << CMD_SHIFT))
#define CMD_SECTOR_ERASE_64KB(addr) ((0xd8 << CMD_SHIFT) | addr)
/* controller interface speeds */ /* controller interface speeds */
#define EP_SPEED_FULL 0x2 /* full speed */ #define EP_SPEED_FULL 0x2 /* full speed */
...@@ -188,28 +199,43 @@ static int erase_chip(struct hfi1_devdata *dd) ...@@ -188,28 +199,43 @@ static int erase_chip(struct hfi1_devdata *dd)
} }
/* /*
* Erase a range using the 32KB erase command. * Erase a range.
*/ */
static int erase_32kb_range(struct hfi1_devdata *dd, u32 start, u32 end) static int erase_range(struct hfi1_devdata *dd, u32 start, u32 len)
{ {
u32 end = start + len;
int ret = 0; int ret = 0;
if (end < start) if (end < start)
return -EINVAL; return -EINVAL;
if ((start & MASK_32KB) || (end & MASK_32KB)) { /* check the end points for the minimum erase */
if ((start & MASK_4KB) || (end & MASK_4KB)) {
dd_dev_err(dd, dd_dev_err(dd,
"%s: non-aligned range (0x%x,0x%x) for a 32KB erase\n", "%s: non-aligned range (0x%x,0x%x) for a 4KB erase\n",
__func__, start, end); __func__, start, end);
return -EINVAL; return -EINVAL;
} }
write_enable(dd); write_enable(dd);
for (; start < end; start += SIZE_32KB) { while (start < end) {
write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_WRITE_ENABLE); write_csr(dd, ASIC_EEP_ADDR_CMD, CMD_WRITE_ENABLE);
/* check in order of largest to smallest */
if (((start & MASK_64KB) == 0) && (start + SIZE_64KB <= end)) {
write_csr(dd, ASIC_EEP_ADDR_CMD,
CMD_SECTOR_ERASE_64KB(start));
start += SIZE_64KB;
} else if (((start & MASK_32KB) == 0) &&
(start + SIZE_32KB <= end)) {
write_csr(dd, ASIC_EEP_ADDR_CMD, write_csr(dd, ASIC_EEP_ADDR_CMD,
CMD_SECTOR_ERASE_32KB(start)); CMD_SECTOR_ERASE_32KB(start));
start += SIZE_32KB;
} else { /* 4KB will work */
write_csr(dd, ASIC_EEP_ADDR_CMD,
CMD_SECTOR_ERASE_4KB(start));
start += SIZE_4KB;
}
ret = wait_for_not_busy(dd); ret = wait_for_not_busy(dd);
if (ret) if (ret)
goto done; goto done;
...@@ -309,6 +335,18 @@ static int write_length(struct hfi1_devdata *dd, u32 start, u32 len, u64 addr) ...@@ -309,6 +335,18 @@ static int write_length(struct hfi1_devdata *dd, u32 start, u32 len, u64 addr)
return ret; return ret;
} }
/* convert an range composite to a length, in bytes */
static inline u32 extract_rlen(u32 composite)
{
return (composite & 0xffff) * EP_PAGE_SIZE;
}
/* convert an range composite to a start, in bytes */
static inline u32 extract_rstart(u32 composite)
{
return (composite >> 16) * EP_PAGE_SIZE;
}
/* /*
* Perform the given operation on the EPROM. Called from user space. The * Perform the given operation on the EPROM. Called from user space. The
* user credentials have already been checked. * user credentials have already been checked.
...@@ -319,6 +357,8 @@ int handle_eprom_command(const struct hfi1_cmd *cmd) ...@@ -319,6 +357,8 @@ int handle_eprom_command(const struct hfi1_cmd *cmd)
{ {
struct hfi1_devdata *dd; struct hfi1_devdata *dd;
u32 dev_id; u32 dev_id;
u32 rlen; /* range length */
u32 rstart; /* range start */
int ret = 0; int ret = 0;
/* /*
...@@ -364,54 +404,29 @@ int handle_eprom_command(const struct hfi1_cmd *cmd) ...@@ -364,54 +404,29 @@ int handle_eprom_command(const struct hfi1_cmd *cmd)
sizeof(u32))) sizeof(u32)))
ret = -EFAULT; ret = -EFAULT;
break; break;
case HFI1_CMD_EP_ERASE_CHIP: case HFI1_CMD_EP_ERASE_CHIP:
ret = erase_chip(dd); ret = erase_chip(dd);
break; break;
case HFI1_CMD_EP_ERASE_P0:
if (cmd->len != P0_SIZE) { case HFI1_CMD_EP_ERASE_RANGE:
ret = -ERANGE; rlen = extract_rlen(cmd->len);
break; rstart = extract_rstart(cmd->len);
} ret = erase_range(dd, rstart, rlen);
ret = erase_32kb_range(dd, 0, cmd->len);
break;
case HFI1_CMD_EP_ERASE_P1:
/* check for overflow */
if (P1_START + cmd->len > ASIC_EEP_ADDR_CMD_EP_ADDR_MASK) {
ret = -ERANGE;
break;
}
ret = erase_32kb_range(dd, P1_START, P1_START + cmd->len);
break;
case HFI1_CMD_EP_READ_P0:
if (cmd->len != P0_SIZE) {
ret = -ERANGE;
break;
}
ret = read_length(dd, 0, cmd->len, cmd->addr);
break;
case HFI1_CMD_EP_READ_P1:
/* check for overflow */
if (P1_START + cmd->len > ASIC_EEP_ADDR_CMD_EP_ADDR_MASK) {
ret = -ERANGE;
break;
}
ret = read_length(dd, P1_START, cmd->len, cmd->addr);
break;
case HFI1_CMD_EP_WRITE_P0:
if (cmd->len > P0_SIZE) {
ret = -ERANGE;
break;
}
ret = write_length(dd, 0, cmd->len, cmd->addr);
break; break;
case HFI1_CMD_EP_WRITE_P1:
/* check for overflow */ case HFI1_CMD_EP_READ_RANGE:
if (P1_START + cmd->len > ASIC_EEP_ADDR_CMD_EP_ADDR_MASK) { rlen = extract_rlen(cmd->len);
ret = -ERANGE; rstart = extract_rstart(cmd->len);
ret = read_length(dd, rstart, rlen, cmd->addr);
break; break;
}
ret = write_length(dd, P1_START, cmd->len, cmd->addr); case HFI1_CMD_EP_WRITE_RANGE:
rlen = extract_rlen(cmd->len);
rstart = extract_rstart(cmd->len);
ret = write_length(dd, rstart, rlen, cmd->addr);
break; break;
default: default:
dd_dev_err(dd, "%s: unexpected command %d\n", dd_dev_err(dd, "%s: unexpected command %d\n",
__func__, cmd->type); __func__, cmd->type);
......
...@@ -234,12 +234,9 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data, ...@@ -234,12 +234,9 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data,
break; break;
case HFI1_CMD_EP_INFO: case HFI1_CMD_EP_INFO:
case HFI1_CMD_EP_ERASE_CHIP: case HFI1_CMD_EP_ERASE_CHIP:
case HFI1_CMD_EP_ERASE_P0: case HFI1_CMD_EP_ERASE_RANGE:
case HFI1_CMD_EP_ERASE_P1: case HFI1_CMD_EP_READ_RANGE:
case HFI1_CMD_EP_READ_P0: case HFI1_CMD_EP_WRITE_RANGE:
case HFI1_CMD_EP_READ_P1:
case HFI1_CMD_EP_WRITE_P0:
case HFI1_CMD_EP_WRITE_P1:
uctxt_required = 0; /* assigned user context not required */ uctxt_required = 0; /* assigned user context not required */
must_be_root = 1; /* validate user */ must_be_root = 1; /* validate user */
copy = 0; copy = 0;
...@@ -393,12 +390,9 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data, ...@@ -393,12 +390,9 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data,
} }
case HFI1_CMD_EP_INFO: case HFI1_CMD_EP_INFO:
case HFI1_CMD_EP_ERASE_CHIP: case HFI1_CMD_EP_ERASE_CHIP:
case HFI1_CMD_EP_ERASE_P0: case HFI1_CMD_EP_ERASE_RANGE:
case HFI1_CMD_EP_ERASE_P1: case HFI1_CMD_EP_READ_RANGE:
case HFI1_CMD_EP_READ_P0: case HFI1_CMD_EP_WRITE_RANGE:
case HFI1_CMD_EP_READ_P1:
case HFI1_CMD_EP_WRITE_P0:
case HFI1_CMD_EP_WRITE_P1:
ret = handle_eprom_command(&cmd); ret = handle_eprom_command(&cmd);
break; break;
} }
......
...@@ -137,12 +137,10 @@ ...@@ -137,12 +137,10 @@
/* separate EPROM commands from normal PSM commands */ /* separate EPROM commands from normal PSM commands */
#define HFI1_CMD_EP_INFO 64 /* read EPROM device ID */ #define HFI1_CMD_EP_INFO 64 /* read EPROM device ID */
#define HFI1_CMD_EP_ERASE_CHIP 65 /* erase whole EPROM */ #define HFI1_CMD_EP_ERASE_CHIP 65 /* erase whole EPROM */
#define HFI1_CMD_EP_ERASE_P0 66 /* erase EPROM partition 0 */ /* range 66-74 no longer used */
#define HFI1_CMD_EP_ERASE_P1 67 /* erase EPROM partition 1 */ #define HFI1_CMD_EP_ERASE_RANGE 75 /* erase EPROM range */
#define HFI1_CMD_EP_READ_P0 68 /* read EPROM partition 0 */ #define HFI1_CMD_EP_READ_RANGE 76 /* read EPROM range */
#define HFI1_CMD_EP_READ_P1 69 /* read EPROM partition 1 */ #define HFI1_CMD_EP_WRITE_RANGE 77 /* write EPROM range */
#define HFI1_CMD_EP_WRITE_P0 70 /* write EPROM partition 0 */
#define HFI1_CMD_EP_WRITE_P1 71 /* write EPROM partition 1 */
#define _HFI1_EVENT_FROZEN_BIT 0 #define _HFI1_EVENT_FROZEN_BIT 0
#define _HFI1_EVENT_LINKDOWN_BIT 1 #define _HFI1_EVENT_LINKDOWN_BIT 1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment