Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1e9e2be3 authored by Adheer Chandravanshi's avatar Adheer Chandravanshi Committed by James Bottomley
Browse files

[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: default avatarAdheer Chandravanshi <adheer.chandravanshi@qlogic.com>
Signed-off-by: default avatarManish Rangankar <manish.rangankar@qlogic.com>
Signed-off-by: default avatarVikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent adaf6990
Loading
Loading
Loading
Loading
+22 −0
Original line number Original line Diff line number Diff line
@@ -159,6 +159,25 @@
#define LSDW(x) ((u32)((u64)(x)))
#define LSDW(x) ((u32)((u64)(x)))
#define MSDW(x) ((u32)((((u64)(x)) >> 16) >> 16))
#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
 * Retry & Timeout Values
 */
 */
@@ -363,6 +382,8 @@ struct ql82xx_hw_data {
	uint32_t flt_iscsi_param;
	uint32_t flt_iscsi_param;
	uint32_t flt_region_chap;
	uint32_t flt_region_chap;
	uint32_t flt_chap_size;
	uint32_t flt_chap_size;
	uint32_t flt_region_ddb;
	uint32_t flt_ddb_size;
};
};


struct qla4_8xxx_legacy_intr_set {
struct qla4_8xxx_legacy_intr_set {
@@ -501,6 +522,7 @@ struct scsi_qla_host {
#define AF_INIT_DONE			1 /* 0x00000002 */
#define AF_INIT_DONE			1 /* 0x00000002 */
#define AF_MBOX_COMMAND			2 /* 0x00000004 */
#define AF_MBOX_COMMAND			2 /* 0x00000004 */
#define AF_MBOX_COMMAND_DONE		3 /* 0x00000008 */
#define AF_MBOX_COMMAND_DONE		3 /* 0x00000008 */
#define AF_ST_DISCOVERY_IN_PROGRESS	4 /* 0x00000010 */
#define AF_INTERRUPTS_ON		6 /* 0x00000040 */
#define AF_INTERRUPTS_ON		6 /* 0x00000040 */
#define AF_GET_CRASH_RECORD		7 /* 0x00000080 */
#define AF_GET_CRASH_RECORD		7 /* 0x00000080 */
#define AF_LINK_UP			8 /* 0x00000100 */
#define AF_LINK_UP			8 /* 0x00000100 */
+34 −0
Original line number Original line Diff line number Diff line
@@ -288,6 +288,8 @@ union external_hw_config_reg {
#define FA_GOLD_RISC_CODE_ADDR_82	0x80000
#define FA_GOLD_RISC_CODE_ADDR_82	0x80000
#define FA_FLASH_ISCSI_CHAP		0x540000
#define FA_FLASH_ISCSI_CHAP		0x540000
#define FA_FLASH_CHAP_SIZE		0xC0000
#define FA_FLASH_CHAP_SIZE		0xC0000
#define FA_FLASH_ISCSI_DDB		0x420000
#define FA_FLASH_DDB_SIZE		0x080000


/* Flash Description Table */
/* Flash Description Table */
struct qla_fdt_layout {
struct qla_fdt_layout {
@@ -348,6 +350,7 @@ struct qla_flt_header {
#define FLT_REG_BOOT_CODE_82	0x78
#define FLT_REG_BOOT_CODE_82	0x78
#define FLT_REG_ISCSI_PARAM	0x65
#define FLT_REG_ISCSI_PARAM	0x65
#define FLT_REG_ISCSI_CHAP	0x63
#define FLT_REG_ISCSI_CHAP	0x63
#define FLT_REG_ISCSI_DDB	0x6A


struct qla_flt_region {
struct qla_flt_region {
	uint32_t code;
	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_NULL_LINK_LOCAL		0x800 /* post connection */
#define DDB_OPT_IPV6_FW_DEFINED_LINK_LOCAL	0x800 /* pre 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_throttle;	/* 02-03 */
	uint16_t exec_count;	/* 04-05 */
	uint16_t exec_count;	/* 04-05 */
	uint16_t res0;	/* 06-07 */
	uint16_t res0;	/* 06-07 */
	uint16_t iscsi_options;	/* 08-09 */
	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 */
	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 */
	uint16_t ip_options;	/* 0C-0D */
#define IPOPT_FRAGMENT_DISABLE	4

	uint16_t iscsi_max_rcv_data_seg_len;	/* 0E-0F */
	uint16_t iscsi_max_rcv_data_seg_len;	/* 0E-0F */
#define BYTE_UNITS	512
#define BYTE_UNITS	512
	uint32_t res1;	/* 10-13 */
	uint32_t res1;	/* 10-13 */
@@ -816,6 +848,8 @@ struct dev_db_entry {
					 * much RAM */
					 * much RAM */
	uint8_t link_local_ipv6_addr[0x10]; /* 1A0-1AF */
	uint8_t link_local_ipv6_addr[0x10]; /* 1A0-1AF */
	uint8_t res5[0x10];	/* 1B0-1BF */
	uint8_t res5[0x10];	/* 1B0-1BF */
#define DDB_NO_LINK	0xFFFF
#define DDB_ISNS	0xFFFD
	uint16_t ddb_link;	/* 1C0-1C1 */
	uint16_t ddb_link;	/* 1C0-1C1 */
	uint16_t chap_tbl_idx;	/* 1C2-1C3 */
	uint16_t chap_tbl_idx;	/* 1C2-1C3 */
	uint16_t tgt_portal_grp; /* 1C4-1C5 */
	uint16_t tgt_portal_grp; /* 1C4-1C5 */
+7 −0
Original line number Original line Diff line number Diff line
@@ -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,
int qla4xxx_post_ping_evt_work(struct scsi_qla_host *ha,
			       uint32_t status, uint32_t pid,
			       uint32_t status, uint32_t pid,
			       uint32_t data_size, uint8_t *data);
			       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 */
/* BSG Functions */
int qla4xxx_bsg_request(struct bsg_job *bsg_job);
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_disable_pause(struct scsi_qla_host *ha);
void qla4_83xx_enable_mbox_intrs(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 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 ql4xextended_error_logging;
extern int ql4xdontresethba;
extern int ql4xdontresethba;
+104 −2
Original line number Original line Diff line number Diff line
@@ -1288,7 +1288,7 @@ int qla4xxx_about_firmware(struct scsi_qla_host *ha)
	return status;
	return status;
}
}


static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, uint32_t options,
			    dma_addr_t dma_addr)
			    dma_addr_t dma_addr)
{
{
	uint32_t mbox_cmd[MBOX_REG_COUNT];
	uint32_t mbox_cmd[MBOX_REG_COUNT];
@@ -1417,6 +1417,52 @@ int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
	return status;
	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,
int qla4xxx_get_chap(struct scsi_qla_host *ha, char *username, char *password,
		     uint16_t idx)
		     uint16_t idx)
{
{
@@ -1510,6 +1556,62 @@ static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
	return ret;
	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
 * qla4xxx_get_chap_index - Get chap index given username and secret
 * @ha: pointer to adapter structure
 * @ha: pointer to adapter structure
+10 −2
Original line number Original line Diff line number Diff line
@@ -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_region_chap =  start;
			hw->flt_chap_size =  le32_to_cpu(region->size);
			hw->flt_chap_size =  le32_to_cpu(region->size);
			break;
			break;
		case FLT_REG_ISCSI_DDB:
			hw->flt_region_ddb =  start;
			hw->flt_ddb_size =  le32_to_cpu(region->size);
			break;
		}
		}
	}
	}
	goto done;
	goto done;
@@ -3168,13 +3172,17 @@ qla4_8xxx_get_flt_info(struct scsi_qla_host *ha, uint32_t flt_addr)
	hw->flt_region_fw       = FA_RISC_CODE_ADDR_82;
	hw->flt_region_fw       = FA_RISC_CODE_ADDR_82;
	hw->flt_region_chap	= FA_FLASH_ISCSI_CHAP >> 2;
	hw->flt_region_chap	= FA_FLASH_ISCSI_CHAP >> 2;
	hw->flt_chap_size	= FA_FLASH_CHAP_SIZE;
	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:
done:
	DEBUG2(ql4_printk(KERN_INFO, ha,
	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,
			  loc, hw->flt_region_flt, hw->flt_region_fdt,
			  hw->flt_region_boot, hw->flt_region_bootload,
			  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
static void
Loading