From cd371e0959a3f2d5df69d50000750f7eefc94659 Mon Sep 17 00:00:00 2001 From: Dean Luick Date: Mon, 16 Nov 2015 21:59:35 -0500 Subject: [PATCH] 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 Signed-off-by: Dean Luick Signed-off-by: Jubin John Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rdma/hfi1/eprom.c | 119 +++++++++++++++------------ drivers/staging/rdma/hfi1/file_ops.c | 18 ++-- 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 @@ #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 @@ done: 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); - 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); + + 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_WRITE_P0: - if (cmd->len > P0_SIZE) { - ret = -ERANGE; - break; - } - ret = write_length(dd, 0, cmd->len, cmd->addr); + + 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_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); 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, 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; } 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 @@ /* 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 -- 2.20.1