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>
This commit is contained in:
parent
5d9157aafb
commit
cd371e0959
|
@ -53,17 +53,26 @@
|
|||
#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 1: the rest
|
||||
* partition 1: 4K config file (sector size)
|
||||
* partition 2: the rest
|
||||
*/
|
||||
#define P0_SIZE (128 * 1024)
|
||||
#define P1_SIZE (4 * 1024)
|
||||
#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 MASK_32KB (SIZE_32KB - 1)
|
||||
|
||||
#define SIZE_64KB (64 * 1024)
|
||||
#define MASK_64KB (SIZE_64KB - 1)
|
||||
|
||||
/* controller page size, in bytes */
|
||||
#define EP_PAGE_SIZE 256
|
||||
#define EEP_PAGE_MASK (EP_PAGE_SIZE - 1)
|
||||
|
@ -75,10 +84,12 @@
|
|||
#define CMD_READ_DATA(addr) ((0x03 << CMD_SHIFT) | addr)
|
||||
#define CMD_READ_SR1 ((0x05 << 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_CHIP_ERASE ((0x60 << CMD_SHIFT))
|
||||
#define CMD_READ_MANUF_DEV_ID ((0x90 << CMD_SHIFT))
|
||||
#define CMD_RELEASE_POWERDOWN_NOID ((0xab << CMD_SHIFT))
|
||||
#define CMD_SECTOR_ERASE_64KB(addr) ((0xd8 << CMD_SHIFT) | addr)
|
||||
|
||||
/* controller interface speeds */
|
||||
#define EP_SPEED_FULL 0x2 /* full speed */
|
||||
|
@ -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;
|
||||
|
||||
if (end < start)
|
||||
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,
|
||||
"%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);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
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_SECTOR_ERASE_32KB(start));
|
||||
/* 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,
|
||||
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);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
@ -309,6 +335,18 @@ static int write_length(struct hfi1_devdata *dd, u32 start, u32 len, u64 addr)
|
|||
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
|
||||
* user credentials have already been checked.
|
||||
|
@ -319,6 +357,8 @@ int handle_eprom_command(const struct hfi1_cmd *cmd)
|
|||
{
|
||||
struct hfi1_devdata *dd;
|
||||
u32 dev_id;
|
||||
u32 rlen; /* range length */
|
||||
u32 rstart; /* range start */
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
|
@ -364,54 +404,29 @@ int handle_eprom_command(const struct hfi1_cmd *cmd)
|
|||
sizeof(u32)))
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
|
||||
case HFI1_CMD_EP_ERASE_CHIP:
|
||||
ret = erase_chip(dd);
|
||||
break;
|
||||
case HFI1_CMD_EP_ERASE_P0:
|
||||
if (cmd->len != P0_SIZE) {
|
||||
ret = -ERANGE;
|
||||
break;
|
||||
}
|
||||
ret = erase_32kb_range(dd, 0, cmd->len);
|
||||
|
||||
case HFI1_CMD_EP_ERASE_RANGE:
|
||||
rlen = extract_rlen(cmd->len);
|
||||
rstart = extract_rstart(cmd->len);
|
||||
ret = erase_range(dd, rstart, rlen);
|
||||
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);
|
||||
|
||||
case HFI1_CMD_EP_READ_RANGE:
|
||||
rlen = extract_rlen(cmd->len);
|
||||
rstart = extract_rstart(cmd->len);
|
||||
ret = read_length(dd, rstart, rlen, cmd->addr);
|
||||
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;
|
||||
case HFI1_CMD_EP_WRITE_P1:
|
||||
/* check for overflow */
|
||||
if (P1_START + cmd->len > ASIC_EEP_ADDR_CMD_EP_ADDR_MASK) {
|
||||
ret = -ERANGE;
|
||||
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;
|
||||
|
||||
default:
|
||||
dd_dev_err(dd, "%s: unexpected command %d\n",
|
||||
__func__, cmd->type);
|
||||
|
|
|
@ -234,12 +234,9 @@ static ssize_t hfi1_file_write(struct file *fp, const char __user *data,
|
|||
break;
|
||||
case HFI1_CMD_EP_INFO:
|
||||
case HFI1_CMD_EP_ERASE_CHIP:
|
||||
case HFI1_CMD_EP_ERASE_P0:
|
||||
case HFI1_CMD_EP_ERASE_P1:
|
||||
case HFI1_CMD_EP_READ_P0:
|
||||
case HFI1_CMD_EP_READ_P1:
|
||||
case HFI1_CMD_EP_WRITE_P0:
|
||||
case HFI1_CMD_EP_WRITE_P1:
|
||||
case HFI1_CMD_EP_ERASE_RANGE:
|
||||
case HFI1_CMD_EP_READ_RANGE:
|
||||
case HFI1_CMD_EP_WRITE_RANGE:
|
||||
uctxt_required = 0; /* assigned user context not required */
|
||||
must_be_root = 1; /* validate user */
|
||||
copy = 0;
|
||||
|
@ -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_ERASE_CHIP:
|
||||
case HFI1_CMD_EP_ERASE_P0:
|
||||
case HFI1_CMD_EP_ERASE_P1:
|
||||
case HFI1_CMD_EP_READ_P0:
|
||||
case HFI1_CMD_EP_READ_P1:
|
||||
case HFI1_CMD_EP_WRITE_P0:
|
||||
case HFI1_CMD_EP_WRITE_P1:
|
||||
case HFI1_CMD_EP_ERASE_RANGE:
|
||||
case HFI1_CMD_EP_READ_RANGE:
|
||||
case HFI1_CMD_EP_WRITE_RANGE:
|
||||
ret = handle_eprom_command(&cmd);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -137,12 +137,10 @@
|
|||
/* separate EPROM commands from normal PSM commands */
|
||||
#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_P0 66 /* erase EPROM partition 0 */
|
||||
#define HFI1_CMD_EP_ERASE_P1 67 /* erase EPROM partition 1 */
|
||||
#define HFI1_CMD_EP_READ_P0 68 /* read EPROM partition 0 */
|
||||
#define HFI1_CMD_EP_READ_P1 69 /* read EPROM partition 1 */
|
||||
#define HFI1_CMD_EP_WRITE_P0 70 /* write EPROM partition 0 */
|
||||
#define HFI1_CMD_EP_WRITE_P1 71 /* write EPROM partition 1 */
|
||||
/* range 66-74 no longer used */
|
||||
#define HFI1_CMD_EP_ERASE_RANGE 75 /* erase EPROM range */
|
||||
#define HFI1_CMD_EP_READ_RANGE 76 /* read EPROM range */
|
||||
#define HFI1_CMD_EP_WRITE_RANGE 77 /* write EPROM range */
|
||||
|
||||
#define _HFI1_EVENT_FROZEN_BIT 0
|
||||
#define _HFI1_EVENT_LINKDOWN_BIT 1
|
||||
|
|
Loading…
Reference in New Issue