[SCSI] qla4xxx: Add flash node mgmt support

This patch allows iscsiadm to manage iSCSI target information stored on
qla4xxx adapter flash on per host basis.

Signed-off-by: Adheer Chandravanshi <adheer.chandravanshi@qlogic.com>
Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
This commit is contained in:
Adheer Chandravanshi 2013-03-22 07:41:31 -04:00 committed by James Bottomley
parent adaf6990dd
commit 1e9e2be3ee
6 changed files with 1824 additions and 4 deletions

View file

@ -159,6 +159,25 @@
#define LSDW(x) ((u32)((u64)(x)))
#define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
#define DEV_TYPE_IPV4 "ipv4"
#define DEV_TYPE_IPV6 "ipv6"
#define DEV_DB_NON_PERSISTENT 0
#define DEV_DB_PERSISTENT 1
#define COPY_ISID(dst_isid, src_isid) { \
int i, j; \
for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;) \
dst_isid[i++] = src_isid[j--]; \
}
#define SET_BITVAL(o, n, v) { \
if (o) \
n |= v; \
else \
n &= ~v; \
}
/*
* Retry & Timeout Values
*/
@ -363,6 +382,8 @@ struct ql82xx_hw_data {
uint32_t flt_iscsi_param;
uint32_t flt_region_chap;
uint32_t flt_chap_size;
uint32_t flt_region_ddb;
uint32_t flt_ddb_size;
};
struct qla4_8xxx_legacy_intr_set {
@ -501,6 +522,7 @@ struct scsi_qla_host {
#define AF_INIT_DONE 1 /* 0x00000002 */
#define AF_MBOX_COMMAND 2 /* 0x00000004 */
#define AF_MBOX_COMMAND_DONE 3 /* 0x00000008 */
#define AF_ST_DISCOVERY_IN_PROGRESS 4 /* 0x00000010 */
#define AF_INTERRUPTS_ON 6 /* 0x00000040 */
#define AF_GET_CRASH_RECORD 7 /* 0x00000080 */
#define AF_LINK_UP 8 /* 0x00000100 */

View file

@ -288,6 +288,8 @@ union external_hw_config_reg {
#define FA_GOLD_RISC_CODE_ADDR_82 0x80000
#define FA_FLASH_ISCSI_CHAP 0x540000
#define FA_FLASH_CHAP_SIZE 0xC0000
#define FA_FLASH_ISCSI_DDB 0x420000
#define FA_FLASH_DDB_SIZE 0x080000
/* Flash Description Table */
struct qla_fdt_layout {
@ -348,6 +350,7 @@ struct qla_flt_header {
#define FLT_REG_BOOT_CODE_82 0x78
#define FLT_REG_ISCSI_PARAM 0x65
#define FLT_REG_ISCSI_CHAP 0x63
#define FLT_REG_ISCSI_DDB 0x6A
struct qla_flt_region {
uint32_t code;
@ -779,12 +782,41 @@ struct dev_db_entry {
#define DDB_OPT_IPV6_NULL_LINK_LOCAL 0x800 /* post connection */
#define DDB_OPT_IPV6_FW_DEFINED_LINK_LOCAL 0x800 /* pre connection */
#define OPT_IS_FW_ASSIGNED_IPV6 11
#define OPT_IPV6_DEVICE 8
#define OPT_AUTO_SENDTGTS_DISABLE 6
#define OPT_DISC_SESSION 4
#define OPT_ENTRY_STATE 3
uint16_t exec_throttle; /* 02-03 */
uint16_t exec_count; /* 04-05 */
uint16_t res0; /* 06-07 */
uint16_t iscsi_options; /* 08-09 */
#define ISCSIOPT_HEADER_DIGEST_EN 13
#define ISCSIOPT_DATA_DIGEST_EN 12
#define ISCSIOPT_IMMEDIATE_DATA_EN 11
#define ISCSIOPT_INITIAL_R2T_EN 10
#define ISCSIOPT_DATA_SEQ_IN_ORDER 9
#define ISCSIOPT_DATA_PDU_IN_ORDER 8
#define ISCSIOPT_CHAP_AUTH_EN 7
#define ISCSIOPT_SNACK_REQ_EN 6
#define ISCSIOPT_DISCOVERY_LOGOUT_EN 5
#define ISCSIOPT_BIDI_CHAP_EN 4
#define ISCSIOPT_DISCOVERY_AUTH_OPTIONAL 3
#define ISCSIOPT_ERL1 1
#define ISCSIOPT_ERL0 0
uint16_t tcp_options; /* 0A-0B */
#define TCPOPT_TIMESTAMP_STAT 6
#define TCPOPT_NAGLE_DISABLE 5
#define TCPOPT_WSF_DISABLE 4
#define TCPOPT_TIMER_SCALE3 3
#define TCPOPT_TIMER_SCALE2 2
#define TCPOPT_TIMER_SCALE1 1
#define TCPOPT_TIMESTAMP_EN 0
uint16_t ip_options; /* 0C-0D */
#define IPOPT_FRAGMENT_DISABLE 4
uint16_t iscsi_max_rcv_data_seg_len; /* 0E-0F */
#define BYTE_UNITS 512
uint32_t res1; /* 10-13 */
@ -816,6 +848,8 @@ struct dev_db_entry {
* much RAM */
uint8_t link_local_ipv6_addr[0x10]; /* 1A0-1AF */
uint8_t res5[0x10]; /* 1B0-1BF */
#define DDB_NO_LINK 0xFFFF
#define DDB_ISNS 0xFFFD
uint16_t ddb_link; /* 1C0-1C1 */
uint16_t chap_tbl_idx; /* 1C2-1C3 */
uint16_t tgt_portal_grp; /* 1C4-1C5 */

View file

@ -191,6 +191,9 @@ int qla4xxx_ping_iocb(struct scsi_qla_host *ha, uint32_t options,
int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha,
uint32_t status, uint32_t pid,
uint32_t data_size, uint8_t *data);
int qla4xxx_flashdb_by_index(struct scsi_qla_host *ha,
struct dev_db_entry *fw_ddb_entry,
dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index);
/* BSG Functions */
int qla4xxx_bsg_request(struct bsg_job *bsg_job);
@ -259,6 +262,10 @@ int qla4_83xx_post_idc_ack(struct scsi_qla_host *ha);
void qla4_83xx_disable_pause(struct scsi_qla_host *ha);
void qla4_83xx_enable_mbox_intrs(struct scsi_qla_host *ha);
int qla4_83xx_can_perform_reset(struct scsi_qla_host *ha);
int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
dma_addr_t dma_addr);
int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username,
char *password, uint16_t chap_index);
extern int ql4xextended_error_logging;
extern int ql4xdontresethba;

View file

@ -1288,8 +1288,8 @@ exit_about_fw:
return status;
}
static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
dma_addr_t dma_addr)
int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
dma_addr_t dma_addr)
{
uint32_t mbox_cmd[MBOX_REG_COUNT];
uint32_t mbox_sts[MBOX_REG_COUNT];
@ -1417,6 +1417,52 @@ exit_bootdb_failed:
return status;
}
int qla4xxx_flashdb_by_index(struct scsi_qla_host *ha,
struct dev_db_entry *fw_ddb_entry,
dma_addr_t fw_ddb_entry_dma, uint16_t ddb_index)
{
uint32_t dev_db_start_offset = FLASH_OFFSET_DB_INFO;
uint32_t dev_db_end_offset;
int status = QLA_ERROR;
memset(fw_ddb_entry, 0, sizeof(*fw_ddb_entry));
if (is_qla40XX(ha)) {
dev_db_start_offset = FLASH_OFFSET_DB_INFO;
} else {
dev_db_start_offset = FLASH_RAW_ACCESS_ADDR +
(ha->hw.flt_region_ddb << 2);
/* flt_ddb_size is DDB table size for both ports
* so divide it by 2 to calculate the offset for second port
*/
if (ha->port_num == 1)
dev_db_start_offset += (ha->hw.flt_ddb_size / 2);
}
dev_db_end_offset = dev_db_start_offset + (ha->hw.flt_ddb_size / 2);
dev_db_start_offset += (ddb_index * sizeof(*fw_ddb_entry));
if (dev_db_start_offset > dev_db_end_offset) {
DEBUG2(ql4_printk(KERN_ERR, ha,
"%s:Invalid DDB index %d", __func__,
ddb_index));
goto exit_fdb_failed;
}
if (qla4xxx_get_flash(ha, fw_ddb_entry_dma, dev_db_start_offset,
sizeof(*fw_ddb_entry)) != QLA_SUCCESS) {
ql4_printk(KERN_ERR, ha, "scsi%ld: %s: Get Flash failed\n",
ha->host_no, __func__);
goto exit_fdb_failed;
}
if (fw_ddb_entry->cookie == DDB_VALID_COOKIE)
status = QLA_SUCCESS;
exit_fdb_failed:
return status;
}
int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
uint16_t idx)
{
@ -1510,6 +1556,62 @@ exit_set_chap:
return ret;
}
int qla4xxx_get_uni_chap_at_index(struct scsi_qla_host *ha, char *username,
char *password, uint16_t chap_index)
{
int rval = QLA_ERROR;
struct ql4_chap_table *chap_table = NULL;
int max_chap_entries;
if (!ha->chap_list) {
ql4_printk(KERN_ERR, ha, "Do not have CHAP table cache\n");
rval = QLA_ERROR;
goto exit_uni_chap;
}
if (!username || !password) {
ql4_printk(KERN_ERR, ha, "No memory for username & secret\n");
rval = QLA_ERROR;
goto exit_uni_chap;
}
if (is_qla80XX(ha))
max_chap_entries = (ha->hw.flt_chap_size / 2) /
sizeof(struct ql4_chap_table);
else
max_chap_entries = MAX_CHAP_ENTRIES_40XX;
if (chap_index > max_chap_entries) {
ql4_printk(KERN_ERR, ha, "Invalid Chap index\n");
rval = QLA_ERROR;
goto exit_uni_chap;
}
mutex_lock(&ha->chap_sem);
chap_table = (struct ql4_chap_table *)ha->chap_list + chap_index;
if (chap_table->cookie != __constant_cpu_to_le16(CHAP_VALID_COOKIE)) {
rval = QLA_ERROR;
goto exit_unlock_uni_chap;
}
if (!(chap_table->flags & BIT_6)) {
ql4_printk(KERN_ERR, ha, "Unidirectional entry not set\n");
rval = QLA_ERROR;
goto exit_unlock_uni_chap;
}
strncpy(password, chap_table->secret, MAX_CHAP_SECRET_LEN);
strncpy(username, chap_table->name, MAX_CHAP_NAME_LEN);
rval = QLA_SUCCESS;
exit_unlock_uni_chap:
mutex_unlock(&ha->chap_sem);
exit_uni_chap:
return rval;
}
/**
* qla4xxx_get_chap_index - Get chap index given username and secret
* @ha: pointer to adapter structure

View file

@ -3154,6 +3154,10 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
hw->flt_region_chap = start;
hw->flt_chap_size = le32_to_cpu(region->size);
break;
case FLT_REG_ISCSI_DDB:
hw->flt_region_ddb = start;
hw->flt_ddb_size = le32_to_cpu(region->size);
break;
}
}
goto done;
@ -3168,13 +3172,17 @@ no_flash_data:
hw->flt_region_fw = FA_RISC_CODE_ADDR_82;
hw->flt_region_chap = FA_FLASH_ISCSI_CHAP >> 2;
hw->flt_chap_size = FA_FLASH_CHAP_SIZE;
hw->flt_region_ddb = FA_FLASH_ISCSI_DDB >> 2;
hw->flt_ddb_size = FA_FLASH_DDB_SIZE;
done:
DEBUG2(ql4_printk(KERN_INFO, ha,
"FLT[%s]: flt=0x%x fdt=0x%x boot=0x%x bootload=0x%x fw=0x%x chap=0x%x\n",
"FLT[%s]: flt=0x%x fdt=0x%x boot=0x%x bootload=0x%x fw=0x%x chap=0x%x chap_size=0x%x ddb=0x%x ddb_size=0x%x\n",
loc, hw->flt_region_flt, hw->flt_region_fdt,
hw->flt_region_boot, hw->flt_region_bootload,
hw->flt_region_fw, hw->flt_region_chap));
hw->flt_region_fw, hw->flt_region_chap,
hw->flt_chap_size, hw->flt_region_ddb,
hw->flt_ddb_size));
}
static void

File diff suppressed because it is too large Load diff