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

Commit 4a4bc2e9 authored by Lalit Chandivade's avatar Lalit Chandivade Committed by James Bottomley
Browse files

[SCSI] qla4xxx: cleanup, make qla4xxx_build_ddb_list short



Make qla4xxx_build_ddb_list shorter by adding more helper functions.

Signed-off-by: default avatarLalit Chandivade <lalit.chandivade@qlogic.com>
Signed-off-by: default avatarVikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent 00c4a09b
Loading
Loading
Loading
Loading
+237 −162
Original line number Diff line number Diff line
@@ -2078,7 +2078,7 @@ void qla4_8xxx_watchdog(struct scsi_qla_host *ha)
	}
}

void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
static void qla4xxx_check_relogin_flash_ddb(struct iscsi_cls_session *cls_sess)
{
	struct iscsi_session *sess;
	struct ddb_entry *ddb_entry;
@@ -3826,16 +3826,14 @@ static int qla4xxx_is_flash_ddb_exists(struct scsi_qla_host *ha,
	return ret;
}

static void qla4xxx_free_nt_list(struct list_head *list_nt)
static void qla4xxx_free_ddb_list(struct list_head *list_ddb)
{
	struct qla_ddb_index  *nt_ddb_idx, *nt_ddb_idx_tmp;
	struct qla_ddb_index  *ddb_idx, *ddb_idx_tmp;

	/* Free up the normaltargets list */
	list_for_each_entry_safe(nt_ddb_idx, nt_ddb_idx_tmp, list_nt, list) {
		list_del_init(&nt_ddb_idx->list);
		vfree(nt_ddb_idx);
	list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
		list_del_init(&ddb_idx->list);
		vfree(ddb_idx);
	}

}

static struct iscsi_endpoint *qla4xxx_get_ep_fwdb(struct scsi_qla_host *ha,
@@ -3934,7 +3932,6 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
			    ip_state == IP_ADDRSTATE_DEPRICATED ||
			    ip_state == IP_ADDRSTATE_DISABLING)
				ip_idx[idx] = -1;

		}

		/* Break if all IP states checked */
@@ -3947,52 +3944,34 @@ static void qla4xxx_wait_for_ip_configuration(struct scsi_qla_host *ha)
	} while (time_after(wtime, jiffies));
}

void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
static void qla4xxx_build_st_list(struct scsi_qla_host *ha,
				  struct list_head *list_st)
{
	struct qla_ddb_index  *st_ddb_idx;
	int max_ddbs;
	int fw_idx_size;
	struct dev_db_entry *fw_ddb_entry;
	dma_addr_t fw_ddb_dma;
	int ret;
	uint32_t idx = 0, next_idx = 0;
	uint32_t state = 0, conn_err = 0;
	uint16_t conn_id;
	struct dev_db_entry *fw_ddb_entry;
	struct ddb_entry *ddb_entry = NULL;
	dma_addr_t fw_ddb_dma;
	struct iscsi_cls_session *cls_sess;
	struct iscsi_session *sess;
	struct iscsi_cls_conn *cls_conn;
	struct iscsi_endpoint *ep;
	uint16_t cmds_max = 32, tmo = 0;
	uint32_t initial_cmdsn = 0;
	struct list_head list_st, list_nt; /* List of sendtargets */
	struct qla_ddb_index  *st_ddb_idx, *st_ddb_idx_tmp;
	int fw_idx_size;
	unsigned long wtime;
	struct qla_ddb_index  *nt_ddb_idx;

	if (!test_bit(AF_LINK_UP, &ha->flags)) {
		set_bit(AF_BUILD_DDB_LIST, &ha->flags);
		ha->is_reset = is_reset;
		return;
	}
	max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
				     MAX_DEV_DB_ENTRIES;
	uint16_t conn_id = 0;

	fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
				      &fw_ddb_dma);
	if (fw_ddb_entry == NULL) {
		DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
		goto exit_ddb_list;
		goto exit_st_list;
	}

	INIT_LIST_HEAD(&list_st);
	INIT_LIST_HEAD(&list_nt);
	max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
				     MAX_DEV_DB_ENTRIES;
	fw_idx_size = sizeof(struct qla_ddb_index);

	for (idx = 0; idx < max_ddbs; idx = next_idx) {
		ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
					      fw_ddb_dma, NULL,
					      &next_idx, &state, &conn_err,
					      NULL, &conn_id);
		ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
					      NULL, &next_idx, &state,
					      &conn_err, NULL, &conn_id);
		if (ret == QLA_ERROR)
			break;

@@ -4009,110 +3988,76 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)

		st_ddb_idx->fw_ddb_idx = idx;

		list_add_tail(&st_ddb_idx->list, &list_st);
		list_add_tail(&st_ddb_idx->list, list_st);
continue_next_st:
		if (next_idx == 0)
			break;
	}

	/* Before issuing conn open mbox, ensure all IPs states are configured
	 * Note, conn open fails if IPs are not configured
	 */
	qla4xxx_wait_for_ip_configuration(ha);

	/* Go thru the STs and fire the sendtargets by issuing conn open mbx */
	list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
		qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
exit_st_list:
	if (fw_ddb_entry)
		dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
}

	/* Wait to ensure all sendtargets are done for min 12 sec wait */
	tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout);
	DEBUG2(ql4_printk(KERN_INFO, ha,
			  "Default time to wait for build ddb %d\n", tmo));
/**
 * qla4xxx_remove_failed_ddb - Remove inactive or failed ddb from list
 * @ha: pointer to adapter structure
 * @list_ddb: List from which failed ddb to be removed
 *
 * Iterate over the list of DDBs and find and remove DDBs that are either in
 * no connection active state or failed state
 **/
static void qla4xxx_remove_failed_ddb(struct scsi_qla_host *ha,
				      struct list_head *list_ddb)
{
	struct qla_ddb_index  *ddb_idx, *ddb_idx_tmp;
	uint32_t next_idx = 0;
	uint32_t state = 0, conn_err = 0;
	int ret;

	wtime = jiffies + (HZ * tmo);
	do {
		list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st,
					 list) {
			ret = qla4xxx_get_fwddb_entry(ha,
						      st_ddb_idx->fw_ddb_idx,
						      NULL, 0, NULL, &next_idx,
						      &state, &conn_err, NULL,
						      NULL);
	list_for_each_entry_safe(ddb_idx, ddb_idx_tmp, list_ddb, list) {
		ret = qla4xxx_get_fwddb_entry(ha, ddb_idx->fw_ddb_idx,
					      NULL, 0, NULL, &next_idx, &state,
					      &conn_err, NULL, NULL);
		if (ret == QLA_ERROR)
			continue;

		if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
		    state == DDB_DS_SESSION_FAILED) {
				list_del_init(&st_ddb_idx->list);
				vfree(st_ddb_idx);
			list_del_init(&ddb_idx->list);
			vfree(ddb_idx);
		}
	}
		schedule_timeout_uninterruptible(HZ / 10);
	} while (time_after(wtime, jiffies));

	/* Free up the sendtargets list */
	list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
		list_del_init(&st_ddb_idx->list);
		vfree(st_ddb_idx);
}

	for (idx = 0; idx < max_ddbs; idx = next_idx) {
		ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry,
					      fw_ddb_dma, NULL,
					      &next_idx, &state, &conn_err,
					      NULL, &conn_id);
		if (ret == QLA_ERROR)
			break;

		if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
			goto continue_next_nt;

		/* Check if NT, then add to list it */
		if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
			goto continue_next_nt;

		if (state == DDB_DS_NO_CONNECTION_ACTIVE ||
		    state == DDB_DS_SESSION_FAILED) {
			DEBUG2(ql4_printk(KERN_INFO, ha,
					  "Adding  DDB to session = 0x%x\n",
					  idx));
			if (is_reset == INIT_ADAPTER) {
				nt_ddb_idx = vmalloc(fw_idx_size);
				if (!nt_ddb_idx)
					break;

				nt_ddb_idx->fw_ddb_idx = idx;

				memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
				       sizeof(struct dev_db_entry));
static int qla4xxx_sess_conn_setup(struct scsi_qla_host *ha,
				   struct dev_db_entry *fw_ddb_entry,
				   int is_reset)
{
	struct iscsi_cls_session *cls_sess;
	struct iscsi_session *sess;
	struct iscsi_cls_conn *cls_conn;
	struct iscsi_endpoint *ep;
	uint16_t cmds_max = 32;
	uint16_t conn_id = 0;
	uint32_t initial_cmdsn = 0;
	int ret = QLA_SUCCESS;

				if (qla4xxx_is_flash_ddb_exists(ha, &list_nt,
						fw_ddb_entry) == QLA_SUCCESS) {
					vfree(nt_ddb_idx);
					goto continue_next_nt;
				}
				list_add_tail(&nt_ddb_idx->list, &list_nt);
			} else if (is_reset == RESET_ADAPTER) {
				if (qla4xxx_is_session_exists(ha,
						   fw_ddb_entry) == QLA_SUCCESS)
					goto continue_next_nt;
			}
	struct ddb_entry *ddb_entry = NULL;

	/* Create session object, with INVALID_ENTRY,
	 * the targer_id would get set when we issue the login
	 */
			cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport,
						ha->host, cmds_max,
						sizeof(struct ddb_entry),
	cls_sess = iscsi_session_setup(&qla4xxx_iscsi_transport, ha->host,
				       cmds_max, sizeof(struct ddb_entry),
				       sizeof(struct ql4_task_data),
				       initial_cmdsn, INVALID_ENTRY);
			if (!cls_sess)
				goto exit_ddb_list;
	if (!cls_sess) {
		ret = QLA_ERROR;
		goto exit_setup;
	}

	/*
			 * iscsi_session_setup increments the driver reference
			 * count which wouldn't let the driver to be unloaded.
	 * so calling module_put function to decrement the
	 * reference count.
	 **/
@@ -4127,11 +4072,12 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)

	qla4xxx_setup_flash_ddb_entry(ha, ddb_entry);

			cls_conn = iscsi_conn_setup(cls_sess,
						    sizeof(struct qla_conn),
						    conn_id);
			if (!cls_conn)
				goto exit_ddb_list;
	cls_conn = iscsi_conn_setup(cls_sess, sizeof(struct qla_conn), conn_id);

	if (!cls_conn) {
		ret = QLA_ERROR;
		goto exit_setup;
	}

	ddb_entry->conn = cls_conn;

@@ -4141,13 +4087,13 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
		ep->conn = cls_conn;
		cls_conn->ep = ep;
	} else {
				DEBUG2(ql4_printk(KERN_ERR, ha,
						  "Unable to get ep\n"));
		DEBUG2(ql4_printk(KERN_ERR, ha, "Unable to get ep\n"));
		ret = QLA_ERROR;
		goto exit_setup;
	}

	/* Update sess/conn params */
			qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess,
						 cls_conn);
	qla4xxx_copy_fwddb_param(ha, fw_ddb_entry, cls_sess, cls_conn);

	if (is_reset == RESET_ADAPTER) {
		iscsi_block_session(cls_sess);
@@ -4159,19 +4105,148 @@ void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
		set_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags);
		set_bit(DF_RELOGIN, &ddb_entry->flags);
	}

exit_setup:
	return ret;
}

static void qla4xxx_build_nt_list(struct scsi_qla_host *ha,
				  struct list_head *list_nt, int is_reset)
{
	struct dev_db_entry *fw_ddb_entry;
	dma_addr_t fw_ddb_dma;
	int max_ddbs;
	int fw_idx_size;
	int ret;
	uint32_t idx = 0, next_idx = 0;
	uint32_t state = 0, conn_err = 0;
	uint16_t conn_id = 0;
	struct qla_ddb_index  *nt_ddb_idx;

	fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
				      &fw_ddb_dma);
	if (fw_ddb_entry == NULL) {
		DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
		goto exit_nt_list;
	}
	max_ddbs =  is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
				     MAX_DEV_DB_ENTRIES;
	fw_idx_size = sizeof(struct qla_ddb_index);

	for (idx = 0; idx < max_ddbs; idx = next_idx) {
		ret = qla4xxx_get_fwddb_entry(ha, idx, fw_ddb_entry, fw_ddb_dma,
					      NULL, &next_idx, &state,
					      &conn_err, NULL, &conn_id);
		if (ret == QLA_ERROR)
			break;

		if (qla4xxx_verify_boot_idx(ha, idx) != QLA_SUCCESS)
			goto continue_next_nt;

		/* Check if NT, then add to list it */
		if (strlen((char *) fw_ddb_entry->iscsi_name) == 0)
			goto continue_next_nt;

		if (!(state == DDB_DS_NO_CONNECTION_ACTIVE ||
		    state == DDB_DS_SESSION_FAILED))
			goto continue_next_nt;

		DEBUG2(ql4_printk(KERN_INFO, ha,
				  "Adding  DDB to session = 0x%x\n", idx));
		if (is_reset == INIT_ADAPTER) {
			nt_ddb_idx = vmalloc(fw_idx_size);
			if (!nt_ddb_idx)
				break;

			nt_ddb_idx->fw_ddb_idx = idx;

			memcpy(&nt_ddb_idx->fw_ddb, fw_ddb_entry,
			       sizeof(struct dev_db_entry));

			if (qla4xxx_is_flash_ddb_exists(ha, list_nt,
					fw_ddb_entry) == QLA_SUCCESS) {
				vfree(nt_ddb_idx);
				goto continue_next_nt;
			}
			list_add_tail(&nt_ddb_idx->list, list_nt);
		} else if (is_reset == RESET_ADAPTER) {
			if (qla4xxx_is_session_exists(ha, fw_ddb_entry) ==
								QLA_SUCCESS)
				goto continue_next_nt;
		}

		ret = qla4xxx_sess_conn_setup(ha, fw_ddb_entry, is_reset);
		if (ret == QLA_ERROR)
			goto exit_nt_list;

continue_next_nt:
		if (next_idx == 0)
			break;
	}
exit_ddb_list:
	qla4xxx_free_nt_list(&list_nt);

exit_nt_list:
	if (fw_ddb_entry)
		dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
}

	qla4xxx_free_ddb_index(ha);
/**
 * qla4xxx_build_ddb_list - Build ddb list and setup sessions
 * @ha: pointer to adapter structure
 * @is_reset: Is this init path or reset path
 *
 * Create a list of sendtargets (st) from firmware DDBs, issue send targets
 * using connection open, then create the list of normal targets (nt)
 * from firmware DDBs. Based on the list of nt setup session and connection
 * objects.
 **/
void qla4xxx_build_ddb_list(struct scsi_qla_host *ha, int is_reset)
{
	uint16_t tmo = 0;
	struct list_head list_st, list_nt;
	struct qla_ddb_index  *st_ddb_idx, *st_ddb_idx_tmp;
	unsigned long wtime;

	if (!test_bit(AF_LINK_UP, &ha->flags)) {
		set_bit(AF_BUILD_DDB_LIST, &ha->flags);
		ha->is_reset = is_reset;
		return;
	}

	INIT_LIST_HEAD(&list_st);
	INIT_LIST_HEAD(&list_nt);

	qla4xxx_build_st_list(ha, &list_st);

	/* Before issuing conn open mbox, ensure all IPs states are configured
	 * Note, conn open fails if IPs are not configured
	 */
	qla4xxx_wait_for_ip_configuration(ha);

	/* Go thru the STs and fire the sendtargets by issuing conn open mbx */
	list_for_each_entry_safe(st_ddb_idx, st_ddb_idx_tmp, &list_st, list) {
		qla4xxx_conn_open(ha, st_ddb_idx->fw_ddb_idx);
	}

	/* Wait to ensure all sendtargets are done for min 12 sec wait */
	tmo = ((ha->def_timeout < LOGIN_TOV) ? LOGIN_TOV : ha->def_timeout);
	DEBUG2(ql4_printk(KERN_INFO, ha,
			  "Default time to wait for build ddb %d\n", tmo));

	wtime = jiffies + (HZ * tmo);
	do {
		qla4xxx_remove_failed_ddb(ha, &list_st);
		schedule_timeout_uninterruptible(HZ / 10);
	} while (time_after(wtime, jiffies));

	/* Free up the sendtargets list */
	qla4xxx_free_ddb_list(&list_st);

	qla4xxx_build_nt_list(ha, &list_nt, is_reset);

	qla4xxx_free_ddb_list(&list_nt);

	qla4xxx_free_ddb_index(ha);
}

/**
 * qla4xxx_probe_adapter - callback function to probe HBA