mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	[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:
		
							parent
							
								
									adaf6990dd
								
							
						
					
					
						commit
						1e9e2be3ee
					
				
					 6 changed files with 1824 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1288,8 +1288,8 @@ int qla4xxx_about_firmware(struct scsi_qla_host *ha)
 | 
			
		|||
	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 @@ int qla4xxx_bootdb_by_index(struct scsi_qla_host *ha,
 | 
			
		|||
	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 @@ static int qla4xxx_set_chap(struct scsi_qla_host *ha, char *username,
 | 
			
		|||
	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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 @@ 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_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
											
										
									
								
							
		Loading…
	
		Reference in a new issue