diff options
Diffstat (limited to 'drivers/scsi/be2iscsi/be_main.c')
| -rw-r--r-- | drivers/scsi/be2iscsi/be_main.c | 4099 | 
1 files changed, 2727 insertions, 1372 deletions
diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 75a85aa9e88..56467df3d6d 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -1,5 +1,5 @@  /** - * Copyright (C) 2005 - 2010 ServerEngines + * Copyright (C) 2005 - 2013 Emulex   * All rights reserved.   *   * This program is free software; you can redistribute it and/or @@ -7,16 +7,16 @@   * as published by the Free Software Foundation.  The full GNU General   * Public License is included in this distribution in the file called COPYING.   * - * Written by: Jayamohan Kallickal (jayamohank@serverengines.com) + * Written by: Jayamohan Kallickal (jayamohan.kallickal@emulex.com)   *   * Contact Information: - * linux-drivers@serverengines.com - * - *  ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 + * linux-drivers@emulex.com   * + * Emulex + * 3333 Susan Street + * Costa Mesa, CA 92626   */ +  #include <linux/reboot.h>  #include <linux/delay.h>  #include <linux/slab.h> @@ -27,8 +27,12 @@  #include <linux/kernel.h>  #include <linux/semaphore.h>  #include <linux/iscsi_boot_sysfs.h> +#include <linux/module.h> +#include <linux/bsg-lib.h>  #include <scsi/libiscsi.h> +#include <scsi/scsi_bsg_iscsi.h> +#include <scsi/scsi_netlink.h>  #include <scsi/scsi_transport_iscsi.h>  #include <scsi/scsi_transport.h>  #include <scsi/scsi_cmnd.h> @@ -38,23 +42,173 @@  #include "be_main.h"  #include "be_iscsi.h"  #include "be_mgmt.h" +#include "be_cmds.h"  static unsigned int be_iopoll_budget = 10;  static unsigned int be_max_phys_size = 64;  static unsigned int enable_msix = 1; -static unsigned int gcrashmode = 0; -static unsigned int num_hba = 0;  MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table);  MODULE_DESCRIPTION(DRV_DESC " " BUILD_STR); -MODULE_AUTHOR("ServerEngines Corporation"); +MODULE_VERSION(BUILD_STR); +MODULE_AUTHOR("Emulex Corporation");  MODULE_LICENSE("GPL");  module_param(be_iopoll_budget, int, 0);  module_param(enable_msix, int, 0);  module_param(be_max_phys_size, uint, S_IRUGO); -MODULE_PARM_DESC(be_max_phys_size, "Maximum Size (In Kilobytes) of physically" -				   "contiguous memory that can be allocated." -				   "Range is 16 - 128"); +MODULE_PARM_DESC(be_max_phys_size, +		"Maximum Size (In Kilobytes) of physically contiguous " +		"memory that can be allocated. Range is 16 - 128"); + +#define beiscsi_disp_param(_name)\ +ssize_t	\ +beiscsi_##_name##_disp(struct device *dev,\ +			struct device_attribute *attrib, char *buf)	\ +{	\ +	struct Scsi_Host *shost = class_to_shost(dev);\ +	struct beiscsi_hba *phba = iscsi_host_priv(shost); \ +	uint32_t param_val = 0;	\ +	param_val = phba->attr_##_name;\ +	return snprintf(buf, PAGE_SIZE, "%d\n",\ +			phba->attr_##_name);\ +} + +#define beiscsi_change_param(_name, _minval, _maxval, _defaval)\ +int \ +beiscsi_##_name##_change(struct beiscsi_hba *phba, uint32_t val)\ +{\ +	if (val >= _minval && val <= _maxval) {\ +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,\ +			    "BA_%d : beiscsi_"#_name" updated "\ +			    "from 0x%x ==> 0x%x\n",\ +			    phba->attr_##_name, val); \ +		phba->attr_##_name = val;\ +		return 0;\ +	} \ +	beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, \ +		    "BA_%d beiscsi_"#_name" attribute "\ +		    "cannot be updated to 0x%x, "\ +		    "range allowed is ["#_minval" - "#_maxval"]\n", val);\ +		return -EINVAL;\ +} + +#define beiscsi_store_param(_name)  \ +ssize_t \ +beiscsi_##_name##_store(struct device *dev,\ +			 struct device_attribute *attr, const char *buf,\ +			 size_t count) \ +{ \ +	struct Scsi_Host  *shost = class_to_shost(dev);\ +	struct beiscsi_hba *phba = iscsi_host_priv(shost);\ +	uint32_t param_val = 0;\ +	if (!isdigit(buf[0]))\ +		return -EINVAL;\ +	if (sscanf(buf, "%i", ¶m_val) != 1)\ +		return -EINVAL;\ +	if (beiscsi_##_name##_change(phba, param_val) == 0) \ +		return strlen(buf);\ +	else \ +		return -EINVAL;\ +} + +#define beiscsi_init_param(_name, _minval, _maxval, _defval) \ +int \ +beiscsi_##_name##_init(struct beiscsi_hba *phba, uint32_t val) \ +{ \ +	if (val >= _minval && val <= _maxval) {\ +		phba->attr_##_name = val;\ +		return 0;\ +	} \ +	beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,\ +		    "BA_%d beiscsi_"#_name" attribute " \ +		    "cannot be updated to 0x%x, "\ +		    "range allowed is ["#_minval" - "#_maxval"]\n", val);\ +	phba->attr_##_name = _defval;\ +	return -EINVAL;\ +} + +#define BEISCSI_RW_ATTR(_name, _minval, _maxval, _defval, _descp) \ +static uint beiscsi_##_name = _defval;\ +module_param(beiscsi_##_name, uint, S_IRUGO);\ +MODULE_PARM_DESC(beiscsi_##_name, _descp);\ +beiscsi_disp_param(_name)\ +beiscsi_change_param(_name, _minval, _maxval, _defval)\ +beiscsi_store_param(_name)\ +beiscsi_init_param(_name, _minval, _maxval, _defval)\ +DEVICE_ATTR(beiscsi_##_name, S_IRUGO | S_IWUSR,\ +	      beiscsi_##_name##_disp, beiscsi_##_name##_store) + +/* + * When new log level added update the + * the MAX allowed value for log_enable + */ +BEISCSI_RW_ATTR(log_enable, 0x00, +		0xFF, 0x00, "Enable logging Bit Mask\n" +		"\t\t\t\tInitialization Events	: 0x01\n" +		"\t\t\t\tMailbox Events		: 0x02\n" +		"\t\t\t\tMiscellaneous Events	: 0x04\n" +		"\t\t\t\tError Handling		: 0x08\n" +		"\t\t\t\tIO Path Events		: 0x10\n" +		"\t\t\t\tConfiguration Path	: 0x20\n" +		"\t\t\t\tiSCSI Protocol		: 0x40\n"); + +DEVICE_ATTR(beiscsi_drvr_ver, S_IRUGO, beiscsi_drvr_ver_disp, NULL); +DEVICE_ATTR(beiscsi_adapter_family, S_IRUGO, beiscsi_adap_family_disp, NULL); +DEVICE_ATTR(beiscsi_fw_ver, S_IRUGO, beiscsi_fw_ver_disp, NULL); +DEVICE_ATTR(beiscsi_phys_port, S_IRUGO, beiscsi_phys_port_disp, NULL); +DEVICE_ATTR(beiscsi_active_session_count, S_IRUGO, +	     beiscsi_active_session_disp, NULL); +DEVICE_ATTR(beiscsi_free_session_count, S_IRUGO, +	     beiscsi_free_session_disp, NULL); +struct device_attribute *beiscsi_attrs[] = { +	&dev_attr_beiscsi_log_enable, +	&dev_attr_beiscsi_drvr_ver, +	&dev_attr_beiscsi_adapter_family, +	&dev_attr_beiscsi_fw_ver, +	&dev_attr_beiscsi_active_session_count, +	&dev_attr_beiscsi_free_session_count, +	&dev_attr_beiscsi_phys_port, +	NULL, +}; + +static char const *cqe_desc[] = { +	"RESERVED_DESC", +	"SOL_CMD_COMPLETE", +	"SOL_CMD_KILLED_DATA_DIGEST_ERR", +	"CXN_KILLED_PDU_SIZE_EXCEEDS_DSL", +	"CXN_KILLED_BURST_LEN_MISMATCH", +	"CXN_KILLED_AHS_RCVD", +	"CXN_KILLED_HDR_DIGEST_ERR", +	"CXN_KILLED_UNKNOWN_HDR", +	"CXN_KILLED_STALE_ITT_TTT_RCVD", +	"CXN_KILLED_INVALID_ITT_TTT_RCVD", +	"CXN_KILLED_RST_RCVD", +	"CXN_KILLED_TIMED_OUT", +	"CXN_KILLED_RST_SENT", +	"CXN_KILLED_FIN_RCVD", +	"CXN_KILLED_BAD_UNSOL_PDU_RCVD", +	"CXN_KILLED_BAD_WRB_INDEX_ERROR", +	"CXN_KILLED_OVER_RUN_RESIDUAL", +	"CXN_KILLED_UNDER_RUN_RESIDUAL", +	"CMD_KILLED_INVALID_STATSN_RCVD", +	"CMD_KILLED_INVALID_R2T_RCVD", +	"CMD_CXN_KILLED_LUN_INVALID", +	"CMD_CXN_KILLED_ICD_INVALID", +	"CMD_CXN_KILLED_ITT_INVALID", +	"CMD_CXN_KILLED_SEQ_OUTOFORDER", +	"CMD_CXN_KILLED_INVALID_DATASN_RCVD", +	"CXN_INVALIDATE_NOTIFY", +	"CXN_INVALIDATE_INDEX_NOTIFY", +	"CMD_INVALIDATED_NOTIFY", +	"UNSOL_HDR_NOTIFY", +	"UNSOL_DATA_NOTIFY", +	"UNSOL_DATA_DIGEST_ERROR_NOTIFY", +	"DRIVERMSG_NOTIFY", +	"CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN", +	"SOL_CMD_KILLED_DIF_ERR", +	"CXN_KILLED_SYN_RCVD", +	"CXN_KILLED_IMM_DATA_RCVD" +};  static int beiscsi_slave_configure(struct scsi_device *sdev)  { @@ -74,24 +228,30 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)  	struct invalidate_command_table *inv_tbl;  	struct be_dma_mem nonemb_cmd;  	unsigned int cid, tag, num_invalidate; +	int rc;  	cls_session = starget_to_session(scsi_target(sc->device));  	session = cls_session->dd_data; -	spin_lock_bh(&session->lock); +	spin_lock_bh(&session->frwd_lock);  	if (!aborted_task || !aborted_task->sc) {  		/* we raced */ -		spin_unlock_bh(&session->lock); +		spin_unlock_bh(&session->frwd_lock);  		return SUCCESS;  	}  	aborted_io_task = aborted_task->dd_data;  	if (!aborted_io_task->scsi_cmnd) {  		/* raced or invalid command */ -		spin_unlock_bh(&session->lock); +		spin_unlock_bh(&session->frwd_lock);  		return SUCCESS;  	} -	spin_unlock_bh(&session->lock); +	spin_unlock_bh(&session->frwd_lock); +	/* Invalidate WRB Posted for this Task */ +	AMAP_SET_BITS(struct amap_iscsi_wrb, invld, +		      aborted_io_task->pwrb_handle->pwrb, +		      1); +  	conn = aborted_task->conn;  	beiscsi_conn = conn->dd_data;  	phba = beiscsi_conn->phba; @@ -107,9 +267,9 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)  				sizeof(struct invalidate_commands_params_in),  				&nonemb_cmd.dma);  	if (nonemb_cmd.va == NULL) { -		SE_DEBUG(DBG_LVL_1, -			 "Failed to allocate memory for" -			 "mgmt_invalidate_icds\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, +			    "BM_%d : Failed to allocate memory for" +			    "mgmt_invalidate_icds\n");  		return FAILED;  	}  	nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); @@ -117,20 +277,20 @@ static int beiscsi_eh_abort(struct scsi_cmnd *sc)  	tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,  				   cid, &nonemb_cmd);  	if (!tag) { -		shost_printk(KERN_WARNING, phba->shost, -			     "mgmt_invalidate_icds could not be" -			     " submitted\n"); +		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, +			    "BM_%d : mgmt_invalidate_icds could not be" +			    "submitted\n");  		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,  				    nonemb_cmd.va, nonemb_cmd.dma);  		return FAILED; -	} else { -		wait_event_interruptible(phba->ctrl.mcc_wait[tag], -					 phba->ctrl.mcc_numtag[tag]); -		free_mcc_tag(&phba->ctrl, tag);  	} -	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, -			    nonemb_cmd.va, nonemb_cmd.dma); + +	rc = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); +	if (rc != -EBUSY) +		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, +				    nonemb_cmd.va, nonemb_cmd.dma); +  	return iscsi_eh_abort(sc);  } @@ -146,15 +306,16 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)  	struct invalidate_command_table *inv_tbl;  	struct be_dma_mem nonemb_cmd;  	unsigned int cid, tag, i, num_invalidate; -	int rc = FAILED; +	int rc;  	/* invalidate iocbs */  	cls_session = starget_to_session(scsi_target(sc->device));  	session = cls_session->dd_data; -	spin_lock_bh(&session->lock); -	if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) -		goto unlock; - +	spin_lock_bh(&session->frwd_lock); +	if (!session->leadconn || session->state != ISCSI_STATE_LOGGED_IN) { +		spin_unlock_bh(&session->frwd_lock); +		return FAILED; +	}  	conn = session->leadconn;  	beiscsi_conn = conn->dd_data;  	phba = beiscsi_conn->phba; @@ -168,24 +329,29 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)  		if (!abrt_task->sc || abrt_task->state == ISCSI_TASK_FREE)  			continue; -		if (abrt_task->sc->device->lun != abrt_task->sc->device->lun) +		if (sc->device->lun != abrt_task->sc->device->lun)  			continue; +		/* Invalidate WRB Posted for this Task */ +		AMAP_SET_BITS(struct amap_iscsi_wrb, invld, +			      abrt_io_task->pwrb_handle->pwrb, +			      1); +  		inv_tbl->cid = cid;  		inv_tbl->icd = abrt_io_task->psgl_handle->sgl_index;  		num_invalidate++;  		inv_tbl++;  	} -	spin_unlock_bh(&session->lock); +	spin_unlock_bh(&session->frwd_lock);  	inv_tbl = phba->inv_tbl;  	nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,  				sizeof(struct invalidate_commands_params_in),  				&nonemb_cmd.dma);  	if (nonemb_cmd.va == NULL) { -		SE_DEBUG(DBG_LVL_1, -			 "Failed to allocate memory for" -			 "mgmt_invalidate_icds\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH, +			    "BM_%d : Failed to allocate memory for" +			    "mgmt_invalidate_icds\n");  		return FAILED;  	}  	nonemb_cmd.size = sizeof(struct invalidate_commands_params_in); @@ -193,95 +359,80 @@ static int beiscsi_eh_device_reset(struct scsi_cmnd *sc)  	tag = mgmt_invalidate_icds(phba, inv_tbl, num_invalidate,  				   cid, &nonemb_cmd);  	if (!tag) { -		shost_printk(KERN_WARNING, phba->shost, -			     "mgmt_invalidate_icds could not be" -			     " submitted\n"); +		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_EH, +			    "BM_%d : mgmt_invalidate_icds could not be" +			    " submitted\n");  		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,  				    nonemb_cmd.va, nonemb_cmd.dma);  		return FAILED; -	} else { -		wait_event_interruptible(phba->ctrl.mcc_wait[tag], -					 phba->ctrl.mcc_numtag[tag]); -		free_mcc_tag(&phba->ctrl, tag);  	} -	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, -			    nonemb_cmd.va, nonemb_cmd.dma); + +	rc = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); +	if (rc != -EBUSY) +		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, +				    nonemb_cmd.va, nonemb_cmd.dma);  	return iscsi_eh_device_reset(sc); -unlock: -	spin_unlock_bh(&session->lock); -	return rc;  }  static ssize_t beiscsi_show_boot_tgt_info(void *data, int type, char *buf)  {  	struct beiscsi_hba *phba = data; +	struct mgmt_session_info *boot_sess = &phba->boot_sess; +	struct mgmt_conn_info *boot_conn = &boot_sess->conn_list[0];  	char *str = buf;  	int rc;  	switch (type) {  	case ISCSI_BOOT_TGT_NAME:  		rc = sprintf(buf, "%.*s\n", -				(int)strlen(phba->boot_sess.target_name), -				(char *)&phba->boot_sess.target_name); +			    (int)strlen(boot_sess->target_name), +			    (char *)&boot_sess->target_name);  		break;  	case ISCSI_BOOT_TGT_IP_ADDR: -		if (phba->boot_sess.conn_list[0].dest_ipaddr.ip_type == 0x1) +		if (boot_conn->dest_ipaddr.ip_type == 0x1)  			rc = sprintf(buf, "%pI4\n", -				(char *)&phba->boot_sess.conn_list[0]. -				dest_ipaddr.ip_address); +				(char *)&boot_conn->dest_ipaddr.addr);  		else  			rc = sprintf(str, "%pI6\n", -				(char *)&phba->boot_sess.conn_list[0]. -				dest_ipaddr.ip_address); +				(char *)&boot_conn->dest_ipaddr.addr);  		break;  	case ISCSI_BOOT_TGT_PORT: -		rc = sprintf(str, "%d\n", phba->boot_sess.conn_list[0]. -				  dest_port); +		rc = sprintf(str, "%d\n", boot_conn->dest_port);  		break;  	case ISCSI_BOOT_TGT_CHAP_NAME:  		rc = sprintf(str,  "%.*s\n", -				      phba->boot_sess.conn_list[0]. -				      negotiated_login_options.auth_data.chap. -				      target_chap_name_length, -				      (char *)&phba->boot_sess.conn_list[0]. -				      negotiated_login_options.auth_data.chap. -				      target_chap_name); +			     boot_conn->negotiated_login_options.auth_data.chap. +			     target_chap_name_length, +			     (char *)&boot_conn->negotiated_login_options. +			     auth_data.chap.target_chap_name);  		break;  	case ISCSI_BOOT_TGT_CHAP_SECRET:  		rc = sprintf(str,  "%.*s\n", -				      phba->boot_sess.conn_list[0]. -				      negotiated_login_options.auth_data.chap. -				      target_secret_length, -				      (char *)&phba->boot_sess.conn_list[0]. -				      negotiated_login_options.auth_data.chap. -				      target_secret); - +			     boot_conn->negotiated_login_options.auth_data.chap. +			     target_secret_length, +			     (char *)&boot_conn->negotiated_login_options. +			     auth_data.chap.target_secret);  		break;  	case ISCSI_BOOT_TGT_REV_CHAP_NAME:  		rc = sprintf(str,  "%.*s\n", -				      phba->boot_sess.conn_list[0]. -				      negotiated_login_options.auth_data.chap. -				      intr_chap_name_length, -				      (char *)&phba->boot_sess.conn_list[0]. -				      negotiated_login_options.auth_data.chap. -				      intr_chap_name); - +			     boot_conn->negotiated_login_options.auth_data.chap. +			     intr_chap_name_length, +			     (char *)&boot_conn->negotiated_login_options. +			     auth_data.chap.intr_chap_name);  		break;  	case ISCSI_BOOT_TGT_REV_CHAP_SECRET: -			rc = sprintf(str,  "%.*s\n", -				      phba->boot_sess.conn_list[0]. -				      negotiated_login_options.auth_data.chap. -				      intr_secret_length, -				      (char *)&phba->boot_sess.conn_list[0]. -				      negotiated_login_options.auth_data.chap. -				      intr_secret); +		rc = sprintf(str,  "%.*s\n", +			     boot_conn->negotiated_login_options.auth_data.chap. +			     intr_secret_length, +			     (char *)&boot_conn->negotiated_login_options. +			     auth_data.chap.intr_secret);  		break;  	case ISCSI_BOOT_TGT_FLAGS: -			rc = sprintf(str, "2\n"); +		rc = sprintf(str, "2\n");  		break;  	case ISCSI_BOOT_TGT_NIC_ASSOC: -			rc = sprintf(str, "0\n"); +		rc = sprintf(str, "0\n");  		break;  	default:  		rc = -ENOSYS; @@ -315,18 +466,14 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)  	switch (type) {  	case ISCSI_BOOT_ETH_FLAGS: -			rc = sprintf(str, "2\n"); +		rc = sprintf(str, "2\n");  		break;  	case ISCSI_BOOT_ETH_INDEX: -			rc = sprintf(str, "0\n"); +		rc = sprintf(str, "0\n");  		break;  	case ISCSI_BOOT_ETH_MAC: -		rc  = beiscsi_get_macaddr(buf, phba); -		if (rc < 0) { -			SE_DEBUG(DBG_LVL_1, "beiscsi_get_macaddr Failed\n"); -			return rc; -		} -	break; +		rc  = beiscsi_get_macaddr(str, phba); +		break;  	default:  		rc = -ENOSYS;  		break; @@ -335,9 +482,9 @@ static ssize_t beiscsi_show_boot_eth_info(void *data, int type, char *buf)  } -static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type) +static umode_t beiscsi_tgt_get_attr_visibility(void *data, int type)  { -	int rc; +	umode_t rc;  	switch (type) {  	case ISCSI_BOOT_TGT_NAME: @@ -358,9 +505,9 @@ static mode_t beiscsi_tgt_get_attr_visibility(void *data, int type)  	return rc;  } -static mode_t beiscsi_ini_get_attr_visibility(void *data, int type) +static umode_t beiscsi_ini_get_attr_visibility(void *data, int type)  { -	int rc; +	umode_t rc;  	switch (type) {  	case ISCSI_BOOT_INI_INITIATOR_NAME: @@ -374,9 +521,9 @@ static mode_t beiscsi_ini_get_attr_visibility(void *data, int type)  } -static mode_t beiscsi_eth_get_attr_visibility(void *data, int type) +static umode_t beiscsi_eth_get_attr_visibility(void *data, int type)  { -	int rc; +	umode_t rc;  	switch (type) {  	case ISCSI_BOOT_ETH_FLAGS: @@ -391,39 +538,6 @@ static mode_t beiscsi_eth_get_attr_visibility(void *data, int type)  	return rc;  } -static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) -{ -	struct iscsi_boot_kobj *boot_kobj; - -	phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); -	if (!phba->boot_kset) -		return -ENOMEM; - -	/* get boot info using mgmt cmd */ -	boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, -					     beiscsi_show_boot_tgt_info, -					     beiscsi_tgt_get_attr_visibility); -	if (!boot_kobj) -		goto free_kset; - -	boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, -					     beiscsi_show_boot_ini_info, -					     beiscsi_ini_get_attr_visibility); -	if (!boot_kobj) -		goto free_kset; - -	boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, -					     beiscsi_show_boot_eth_info, -					     beiscsi_eth_get_attr_visibility); -	if (!boot_kobj) -		goto free_kset; -	return 0; - -free_kset: -	iscsi_boot_destroy_kset(phba->boot_kset); -	return -ENOMEM; -} -  /*------------------- PCI Driver operations and data ----------------- */  static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {  	{ PCI_DEVICE(BE_VENDOR_ID, BE_DEVICE_ID1) }, @@ -431,13 +545,15 @@ static DEFINE_PCI_DEVICE_TABLE(beiscsi_pci_id_table) = {  	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID1) },  	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID2) },  	{ PCI_DEVICE(BE_VENDOR_ID, OC_DEVICE_ID3) }, +	{ PCI_DEVICE(ELX_VENDOR_ID, OC_SKH_ID1) },  	{ 0 }  };  MODULE_DEVICE_TABLE(pci, beiscsi_pci_id_table); +  static struct scsi_host_template beiscsi_sht = {  	.module = THIS_MODULE, -	.name = "ServerEngines 10Gbe open-iscsi Initiator Driver", +	.name = "Emulex 10Gbe open-iscsi Initiator Driver",  	.proc_name = DRV_NAME,  	.queuecommand = iscsi_queuecommand,  	.change_queue_depth = iscsi_change_queue_depth, @@ -446,12 +562,15 @@ static struct scsi_host_template beiscsi_sht = {  	.eh_abort_handler = beiscsi_eh_abort,  	.eh_device_reset_handler = beiscsi_eh_device_reset,  	.eh_target_reset_handler = iscsi_eh_session_reset, +	.shost_attrs = beiscsi_attrs,  	.sg_tablesize = BEISCSI_SGLIST_ELEMENTS,  	.can_queue = BE2_IO_DEPTH,  	.this_id = -1,  	.max_sectors = BEISCSI_MAX_SECTORS,  	.cmd_per_lun = BEISCSI_CMD_PER_LUN,  	.use_clustering = ENABLE_CLUSTERING, +	.vendor_id = SCSI_NL_VID_TYPE_PCI | BE_VENDOR_ID, +  };  static struct scsi_transport_template *beiscsi_scsi_transport; @@ -463,8 +582,8 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)  	shost = iscsi_host_alloc(&beiscsi_sht, sizeof(*phba), 0);  	if (!shost) { -		dev_err(&pcidev->dev, "beiscsi_hba_alloc -" -			"iscsi_host_alloc failed\n"); +		dev_err(&pcidev->dev, +			"beiscsi_hba_alloc - iscsi_host_alloc failed\n");  		return NULL;  	}  	shost->dma_boundary = pcidev->dma_mask; @@ -478,24 +597,9 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev)  	phba->shost = shost;  	phba->pcidev = pci_dev_get(pcidev);  	pci_set_drvdata(pcidev, phba); - -	if (iscsi_host_add(shost, &phba->pcidev->dev)) -		goto free_devices; - -	if (beiscsi_setup_boot_info(phba)) -		/* -		 * log error but continue, because we may not be using -		 * iscsi boot. -		 */ -		shost_printk(KERN_ERR, phba->shost, "Could not set up " -		"iSCSI boot info."); +	phba->interface_handle = 0xFFFFFFFF;  	return phba; - -free_devices: -	pci_dev_put(phba->pcidev); -	iscsi_host_free(phba->shost); -	return NULL;  }  static void beiscsi_unmap_pci_function(struct beiscsi_hba *phba) @@ -561,14 +665,25 @@ static int beiscsi_enable_pci(struct pci_dev *pcidev)  	ret = pci_enable_device(pcidev);  	if (ret) { -		dev_err(&pcidev->dev, "beiscsi_enable_pci - enable device " -			"failed. Returning -ENODEV\n"); +		dev_err(&pcidev->dev, +			"beiscsi_enable_pci - enable device failed\n");  		return ret;  	}  	pci_set_master(pcidev); -	if (pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64))) { -		ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(32)); +	ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(64)); +	if (ret) { +		ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32)); +		if (ret) { +			dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n"); +			pci_disable_device(pcidev); +			return ret; +		} else { +			ret = pci_set_consistent_dma_mask(pcidev, +							  DMA_BIT_MASK(32)); +		} +	} else { +		ret = pci_set_consistent_dma_mask(pcidev, DMA_BIT_MASK(64));  		if (ret) {  			dev_err(&pcidev->dev, "Could not set PCI DMA Mask\n");  			pci_disable_device(pcidev); @@ -595,8 +710,7 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)  						  &mbox_mem_alloc->dma);  	if (!mbox_mem_alloc->va) {  		beiscsi_unmap_pci_function(phba); -		status = -ENOMEM; -		return status; +		return -ENOMEM;  	}  	mbox_mem_align->size = sizeof(struct be_mcc_mailbox); @@ -610,29 +724,85 @@ static int be_ctrl_init(struct beiscsi_hba *phba, struct pci_dev *pdev)  	return status;  } +/** + * beiscsi_get_params()- Set the config paramters + * @phba: ptr  device priv structure + **/  static void beiscsi_get_params(struct beiscsi_hba *phba)  { -	phba->params.ios_per_ctrl = (phba->fw_config.iscsi_icd_count -				    - (phba->fw_config.iscsi_cid_count -				    + BE2_TMFS -				    + BE2_NOPOUT_REQ)); -	phba->params.cxns_per_ctrl = phba->fw_config.iscsi_cid_count; -	phba->params.asyncpdus_per_ctrl = phba->fw_config.iscsi_cid_count * 2; -	phba->params.icds_per_ctrl = phba->fw_config.iscsi_icd_count;; +	uint32_t total_cid_count = 0; +	uint32_t total_icd_count = 0; +	uint8_t ulp_num = 0; + +	total_cid_count = BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP0) + +			  BEISCSI_GET_CID_COUNT(phba, BEISCSI_ULP1); + +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		uint32_t align_mask = 0; +		uint32_t icd_post_per_page = 0; +		uint32_t icd_count_unavailable = 0; +		uint32_t icd_start = 0, icd_count = 0; +		uint32_t icd_start_align = 0, icd_count_align = 0; + +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { +			icd_start = phba->fw_config.iscsi_icd_start[ulp_num]; +			icd_count = phba->fw_config.iscsi_icd_count[ulp_num]; + +			/* Get ICD count that can be posted on each page */ +			icd_post_per_page = (PAGE_SIZE / (BE2_SGE * +					     sizeof(struct iscsi_sge))); +			align_mask = (icd_post_per_page - 1); + +			/* Check if icd_start is aligned ICD per page posting */ +			if (icd_start % icd_post_per_page) { +				icd_start_align = ((icd_start + +						    icd_post_per_page) & +						    ~(align_mask)); +				phba->fw_config. +					iscsi_icd_start[ulp_num] = +					icd_start_align; +			} + +			icd_count_align = (icd_count & ~align_mask); + +			/* ICD discarded in the process of alignment */ +			if (icd_start_align) +				icd_count_unavailable = ((icd_start_align - +							  icd_start) + +							 (icd_count - +							  icd_count_align)); + +			/* Updated ICD count available */ +			phba->fw_config.iscsi_icd_count[ulp_num] = (icd_count - +					icd_count_unavailable); + +			beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +					"BM_%d : Aligned ICD values\n" +					"\t ICD Start : %d\n" +					"\t ICD Count : %d\n" +					"\t ICD Discarded : %d\n", +					phba->fw_config. +					iscsi_icd_start[ulp_num], +					phba->fw_config. +					iscsi_icd_count[ulp_num], +					icd_count_unavailable); +			break; +		} +	} + +	total_icd_count = phba->fw_config.iscsi_icd_count[ulp_num]; +	phba->params.ios_per_ctrl = (total_icd_count - +				    (total_cid_count + +				     BE2_TMFS + BE2_NOPOUT_REQ)); +	phba->params.cxns_per_ctrl = total_cid_count; +	phba->params.asyncpdus_per_ctrl = total_cid_count; +	phba->params.icds_per_ctrl = total_icd_count;  	phba->params.num_sge_per_io = BE2_SGE;  	phba->params.defpdu_hdr_sz = BE2_DEFPDU_HDR_SZ;  	phba->params.defpdu_data_sz = BE2_DEFPDU_DATA_SZ;  	phba->params.eq_timer = 64; -	phba->params.num_eq_entries = -	    (((BE2_CMDS_PER_CXN * 2 + phba->fw_config.iscsi_cid_count * 2 -				    + BE2_TMFS) / 512) + 1) * 512; -	phba->params.num_eq_entries = (phba->params.num_eq_entries < 1024) -				? 1024 : phba->params.num_eq_entries; -	SE_DEBUG(DBG_LVL_8, "phba->params.num_eq_entries=%d\n", -			     phba->params.num_eq_entries); -	phba->params.num_cq_entries = -	    (((BE2_CMDS_PER_CXN * 2 +  phba->fw_config.iscsi_cid_count * 2 -				    + BE2_TMFS) / 512) + 1) * 512; +	phba->params.num_eq_entries = 1024; +	phba->params.num_cq_entries = 1024;  	phba->params.wrbs_per_cxn = 256;  } @@ -642,14 +812,23 @@ static void hwi_ring_eq_db(struct beiscsi_hba *phba,  			   unsigned char rearm, unsigned char event)  {  	u32 val = 0; -	val |= id & DB_EQ_RING_ID_MASK; +  	if (rearm)  		val |= 1 << DB_EQ_REARM_SHIFT;  	if (clr_interrupt)  		val |= 1 << DB_EQ_CLR_SHIFT;  	if (event)  		val |= 1 << DB_EQ_EVNT_SHIFT; +  	val |= num_processed << DB_EQ_NUM_POPPED_SHIFT; +	/* Setting lower order EQ_ID Bits */ +	val |= (id & DB_EQ_RING_ID_LOW_MASK); + +	/* Setting Higher order EQ_ID Bits */ +	val |= (((id >> DB_EQ_HIGH_FEILD_SHIFT) & +		  DB_EQ_RING_ID_HIGH_MASK) +		  << DB_EQ_HIGH_SET_SHIFT); +  	iowrite32(val, phba->db_va + DB_EQ_OFFSET);  } @@ -673,8 +852,6 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)  	phba =  pbe_eq->phba;  	mcc = &phba->ctrl.mcc_obj.cq;  	eqe = queue_tail_node(eq); -	if (!eqe) -		SE_DEBUG(DBG_LVL_1, "eqe is NULL\n");  	num_eq_processed = 0; @@ -684,7 +861,7 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)  		     resource_id) / 32] &  		     EQE_RESID_MASK) >> 16) == mcc->id) {  			spin_lock_irqsave(&phba->isr_lock, flags); -			phba->todo_mcc_cq = 1; +			pbe_eq->todo_mcc_cq = true;  			spin_unlock_irqrestore(&phba->isr_lock, flags);  		}  		AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); @@ -692,8 +869,8 @@ static irqreturn_t be_isr_mcc(int irq, void *dev_id)  		eqe = queue_tail_node(eq);  		num_eq_processed++;  	} -	if (phba->todo_mcc_cq) -		queue_work(phba->wq, &phba->work_cqs); +	if (pbe_eq->todo_mcc_cq) +		queue_work(phba->wq, &pbe_eq->work_cqs);  	if (num_eq_processed)  		hwi_ring_eq_db(phba, eq->id, 1,	num_eq_processed, 1, 1); @@ -713,51 +890,29 @@ static irqreturn_t be_isr_msix(int irq, void *dev_id)  	struct be_queue_info *cq;  	unsigned int num_eq_processed;  	struct be_eq_obj *pbe_eq; -	unsigned long flags;  	pbe_eq = dev_id;  	eq = &pbe_eq->q;  	cq = pbe_eq->cq;  	eqe = queue_tail_node(eq); -	if (!eqe) -		SE_DEBUG(DBG_LVL_1, "eqe is NULL\n");  	phba = pbe_eq->phba;  	num_eq_processed = 0; -	if (blk_iopoll_enabled) { -		while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] -					& EQE_VALID_MASK) { -			if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) -				blk_iopoll_sched(&pbe_eq->iopoll); - -			AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); -			queue_tail_inc(eq); -			eqe = queue_tail_node(eq); -			num_eq_processed++; -		} -		if (num_eq_processed) -			hwi_ring_eq_db(phba, eq->id, 1,	num_eq_processed, 0, 1); +	while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] +				& EQE_VALID_MASK) { +		if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) +			blk_iopoll_sched(&pbe_eq->iopoll); -		return IRQ_HANDLED; -	} else { -		while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] -						& EQE_VALID_MASK) { -			spin_lock_irqsave(&phba->isr_lock, flags); -			phba->todo_cq = 1; -			spin_unlock_irqrestore(&phba->isr_lock, flags); -			AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); -			queue_tail_inc(eq); -			eqe = queue_tail_node(eq); -			num_eq_processed++; -		} -		if (phba->todo_cq) -			queue_work(phba->wq, &phba->work_cqs); +		AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); +		queue_tail_inc(eq); +		eqe = queue_tail_node(eq); +		num_eq_processed++; +	} -		if (num_eq_processed) -			hwi_ring_eq_db(phba, eq->id, 1, num_eq_processed, 1, 1); +	if (num_eq_processed) +		hwi_ring_eq_db(phba, eq->id, 1,	num_eq_processed, 0, 1); -		return IRQ_HANDLED; -	} +	return IRQ_HANDLED;  }  /** @@ -772,7 +927,6 @@ static irqreturn_t be_isr(int irq, void *dev_id)  	struct hwi_context_memory *phwi_context;  	struct be_eq_entry *eqe = NULL;  	struct be_queue_info *eq; -	struct be_queue_info *cq;  	struct be_queue_info *mcc;  	unsigned long flags, index;  	unsigned int num_mcceq_processed, num_ioeq_processed; @@ -781,7 +935,7 @@ static irqreturn_t be_isr(int irq, void *dev_id)  	int isr;  	phba = dev_id; -	ctrl = &phba->ctrl;; +	ctrl = &phba->ctrl;  	isr = ioread32(ctrl->csr + CEV_ISR0_OFFSET +  		       (PCI_FUNC(ctrl->pdev->devfn) * CEV_ISR_SIZE));  	if (!isr) @@ -795,77 +949,43 @@ static irqreturn_t be_isr(int irq, void *dev_id)  	mcc = &phba->ctrl.mcc_obj.cq;  	index = 0;  	eqe = queue_tail_node(eq); -	if (!eqe) -		SE_DEBUG(DBG_LVL_1, "eqe is NULL\n");  	num_ioeq_processed = 0;  	num_mcceq_processed = 0; -	if (blk_iopoll_enabled) { -		while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] -					& EQE_VALID_MASK) { -			if (((eqe->dw[offsetof(struct amap_eq_entry, -			     resource_id) / 32] & -			     EQE_RESID_MASK) >> 16) == mcc->id) { -				spin_lock_irqsave(&phba->isr_lock, flags); -				phba->todo_mcc_cq = 1; -				spin_unlock_irqrestore(&phba->isr_lock, flags); -				num_mcceq_processed++; -			} else { -				if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) -					blk_iopoll_sched(&pbe_eq->iopoll); -				num_ioeq_processed++; -			} -			AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); -			queue_tail_inc(eq); -			eqe = queue_tail_node(eq); -		} -		if (num_ioeq_processed || num_mcceq_processed) { -			if (phba->todo_mcc_cq) -				queue_work(phba->wq, &phba->work_cqs); - -			if ((num_mcceq_processed) && (!num_ioeq_processed)) -				hwi_ring_eq_db(phba, eq->id, 0, -					      (num_ioeq_processed + -					       num_mcceq_processed) , 1, 1); -			else -				hwi_ring_eq_db(phba, eq->id, 0, -					       (num_ioeq_processed + -						num_mcceq_processed), 0, 1); - -			return IRQ_HANDLED; -		} else -			return IRQ_NONE; -	} else { -		cq = &phwi_context->be_cq[0]; -		while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] -						& EQE_VALID_MASK) { - -			if (((eqe->dw[offsetof(struct amap_eq_entry, -			     resource_id) / 32] & -			     EQE_RESID_MASK) >> 16) != cq->id) { -				spin_lock_irqsave(&phba->isr_lock, flags); -				phba->todo_mcc_cq = 1; -				spin_unlock_irqrestore(&phba->isr_lock, flags); -			} else { -				spin_lock_irqsave(&phba->isr_lock, flags); -				phba->todo_cq = 1; -				spin_unlock_irqrestore(&phba->isr_lock, flags); -			} -			AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); -			queue_tail_inc(eq); -			eqe = queue_tail_node(eq); +	while (eqe->dw[offsetof(struct amap_eq_entry, valid) / 32] +				& EQE_VALID_MASK) { +		if (((eqe->dw[offsetof(struct amap_eq_entry, +		     resource_id) / 32] & +		     EQE_RESID_MASK) >> 16) == mcc->id) { +			spin_lock_irqsave(&phba->isr_lock, flags); +			pbe_eq->todo_mcc_cq = true; +			spin_unlock_irqrestore(&phba->isr_lock, flags); +			num_mcceq_processed++; +		} else { +			if (!blk_iopoll_sched_prep(&pbe_eq->iopoll)) +				blk_iopoll_sched(&pbe_eq->iopoll);  			num_ioeq_processed++;  		} -		if (phba->todo_cq || phba->todo_mcc_cq) -			queue_work(phba->wq, &phba->work_cqs); +		AMAP_SET_BITS(struct amap_eq_entry, valid, eqe, 0); +		queue_tail_inc(eq); +		eqe = queue_tail_node(eq); +	} +	if (num_ioeq_processed || num_mcceq_processed) { +		if (pbe_eq->todo_mcc_cq) +			queue_work(phba->wq, &pbe_eq->work_cqs); -		if (num_ioeq_processed) { +		if ((num_mcceq_processed) && (!num_ioeq_processed))  			hwi_ring_eq_db(phba, eq->id, 0, -				       num_ioeq_processed, 1, 1); -			return IRQ_HANDLED; -		} else -			return IRQ_NONE; -	} +				      (num_ioeq_processed + +				       num_mcceq_processed) , 1, 1); +		else +			hwi_ring_eq_db(phba, eq->id, 0, +				       (num_ioeq_processed + +					num_mcceq_processed), 0, 1); + +		return IRQ_HANDLED; +	} else +		return IRQ_NONE;  }  static int beiscsi_init_irqs(struct beiscsi_hba *phba) @@ -874,33 +994,49 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)  	struct hwi_controller *phwi_ctrlr;  	struct hwi_context_memory *phwi_context;  	int ret, msix_vec, i, j; -	char desc[32];  	phwi_ctrlr = phba->phwi_ctrlr;  	phwi_context = phwi_ctrlr->phwi_ctxt;  	if (phba->msix_enabled) {  		for (i = 0; i < phba->num_cpus; i++) { -			sprintf(desc, "beiscsi_msix_%04x", i); +			phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, +						    GFP_KERNEL); +			if (!phba->msi_name[i]) { +				ret = -ENOMEM; +				goto free_msix_irqs; +			} + +			sprintf(phba->msi_name[i], "beiscsi_%02x_%02x", +				phba->shost->host_no, i);  			msix_vec = phba->msix_entries[i].vector; -			ret = request_irq(msix_vec, be_isr_msix, 0, desc, +			ret = request_irq(msix_vec, be_isr_msix, 0, +					  phba->msi_name[i],  					  &phwi_context->be_eq[i]);  			if (ret) { -				shost_printk(KERN_ERR, phba->shost, -					     "beiscsi_init_irqs-Failed to" -					     "register msix for i = %d\n", i); -				if (!i) -					return ret; +				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +					    "BM_%d : beiscsi_init_irqs-Failed to" +					    "register msix for i = %d\n", +					    i); +				kfree(phba->msi_name[i]);  				goto free_msix_irqs;  			}  		} +		phba->msi_name[i] = kzalloc(BEISCSI_MSI_NAME, GFP_KERNEL); +		if (!phba->msi_name[i]) { +			ret = -ENOMEM; +			goto free_msix_irqs; +		} +		sprintf(phba->msi_name[i], "beiscsi_mcc_%02x", +			phba->shost->host_no);  		msix_vec = phba->msix_entries[i].vector; -		ret = request_irq(msix_vec, be_isr_mcc, 0, "beiscsi_msix_mcc", +		ret = request_irq(msix_vec, be_isr_mcc, 0, phba->msi_name[i],  				  &phwi_context->be_eq[i]);  		if (ret) { -			shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-" -				     "Failed to register beiscsi_msix_mcc\n"); -			i++; +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT , +				    "BM_%d : beiscsi_init_irqs-" +				    "Failed to register beiscsi_msix_mcc\n"); +			kfree(phba->msi_name[i]);  			goto free_msix_irqs;  		} @@ -908,34 +1044,47 @@ static int beiscsi_init_irqs(struct beiscsi_hba *phba)  		ret = request_irq(pcidev->irq, be_isr, IRQF_SHARED,  				  "beiscsi", phba);  		if (ret) { -			shost_printk(KERN_ERR, phba->shost, "beiscsi_init_irqs-" -				     "Failed to register irq\\n"); +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : beiscsi_init_irqs-" +				    "Failed to register irq\\n");  			return ret;  		}  	}  	return 0;  free_msix_irqs: -	for (j = i - 1; j == 0; j++) +	for (j = i - 1; j >= 0; j--) { +		kfree(phba->msi_name[j]); +		msix_vec = phba->msix_entries[j].vector;  		free_irq(msix_vec, &phwi_context->be_eq[j]); +	}  	return ret;  } -static void hwi_ring_cq_db(struct beiscsi_hba *phba, +void hwi_ring_cq_db(struct beiscsi_hba *phba,  			   unsigned int id, unsigned int num_processed,  			   unsigned char rearm, unsigned char event)  {  	u32 val = 0; -	val |= id & DB_CQ_RING_ID_MASK; +  	if (rearm)  		val |= 1 << DB_CQ_REARM_SHIFT; +  	val |= num_processed << DB_CQ_NUM_POPPED_SHIFT; + +	/* Setting lower order CQ_ID Bits */ +	val |= (id & DB_CQ_RING_ID_LOW_MASK); + +	/* Setting Higher order CQ_ID Bits */ +	val |= (((id >> DB_CQ_HIGH_FEILD_SHIFT) & +		  DB_CQ_RING_ID_HIGH_MASK) +		  << DB_CQ_HIGH_SET_SHIFT); +  	iowrite32(val, phba->db_va + DB_CQ_OFFSET);  }  static unsigned int  beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,  			  struct beiscsi_hba *phba, -			  unsigned short cid,  			  struct pdu_base *ppdu,  			  unsigned long pdu_len,  			  void *pbuffer, unsigned long buf_len) @@ -957,7 +1106,9 @@ beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,  	case ISCSI_OP_REJECT:  		WARN_ON(!pbuffer);  		WARN_ON(!(buf_len == 48)); -		SE_DEBUG(DBG_LVL_1, "In ISCSI_OP_REJECT\n"); +		beiscsi_log(phba, KERN_ERR, +			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, +			    "BM_%d : In ISCSI_OP_REJECT\n");  		break;  	case ISCSI_OP_LOGIN_RSP:  	case ISCSI_OP_TEXT_RSP: @@ -967,17 +1118,18 @@ beiscsi_process_async_pdu(struct beiscsi_conn *beiscsi_conn,  		login_hdr->itt = io_task->libiscsi_itt;  		break;  	default: -		shost_printk(KERN_WARNING, phba->shost, -			     "Unrecognized opcode 0x%x in async msg\n", -			     (ppdu-> +		beiscsi_log(phba, KERN_WARNING, +			    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +			    "BM_%d : Unrecognized opcode 0x%x in async msg\n", +			    (ppdu->  			     dw[offsetof(struct amap_pdu_base, opcode) / 32] -						& PDUBASE_OPCODE_MASK)); +			     & PDUBASE_OPCODE_MASK));  		return 1;  	} -	spin_lock_bh(&session->lock); +	spin_lock_bh(&session->back_lock);  	__iscsi_complete_pdu(conn, (struct iscsi_hdr *)ppdu, pbuffer, buf_len); -	spin_unlock_bh(&session->lock); +	spin_unlock_bh(&session->back_lock);  	return 0;  } @@ -986,9 +1138,11 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)  	struct sgl_handle *psgl_handle;  	if (phba->io_sgl_hndl_avbl) { -		SE_DEBUG(DBG_LVL_8, -			 "In alloc_io_sgl_handle,io_sgl_alloc_index=%d\n", -			 phba->io_sgl_alloc_index); +		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, +			    "BM_%d : In alloc_io_sgl_handle," +			    " io_sgl_alloc_index=%d\n", +			    phba->io_sgl_alloc_index); +  		psgl_handle = phba->io_sgl_hndl_base[phba->  						io_sgl_alloc_index];  		phba->io_sgl_hndl_base[phba->io_sgl_alloc_index] = NULL; @@ -1006,17 +1160,20 @@ static struct sgl_handle *alloc_io_sgl_handle(struct beiscsi_hba *phba)  static void  free_io_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)  { -	SE_DEBUG(DBG_LVL_8, "In free_,io_sgl_free_index=%d\n", -		 phba->io_sgl_free_index); +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, +		    "BM_%d : In free_,io_sgl_free_index=%d\n", +		    phba->io_sgl_free_index); +  	if (phba->io_sgl_hndl_base[phba->io_sgl_free_index]) {  		/*  		 * this can happen if clean_task is called on a task that  		 * failed in xmit_task or alloc_pdu.  		 */ -		 SE_DEBUG(DBG_LVL_8, -			 "Double Free in IO SGL io_sgl_free_index=%d," -			 "value there=%p\n", phba->io_sgl_free_index, -			 phba->io_sgl_hndl_base[phba->io_sgl_free_index]); +		 beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_IO, +			     "BM_%d : Double Free in IO SGL io_sgl_free_index=%d," +			     "value there=%p\n", phba->io_sgl_free_index, +			     phba->io_sgl_hndl_base +			     [phba->io_sgl_free_index]);  		return;  	}  	phba->io_sgl_hndl_base[phba->io_sgl_free_index] = psgl_handle; @@ -1039,9 +1196,10 @@ struct wrb_handle *alloc_wrb_handle(struct beiscsi_hba *phba, unsigned int cid)  	struct hwi_wrb_context *pwrb_context;  	struct hwi_controller *phwi_ctrlr;  	struct wrb_handle *pwrb_handle, *pwrb_handle_tmp; +	uint16_t cri_index = BE_GET_CRI_FROM_CID(cid);  	phwi_ctrlr = phba->phwi_ctrlr; -	pwrb_context = &phwi_ctrlr->wrb_context[cid]; +	pwrb_context = &phwi_ctrlr->wrb_context[cri_index];  	if (pwrb_context->wrb_handles_available >= 2) {  		pwrb_handle = pwrb_context->pwrb_handle_base[  					    pwrb_context->alloc_index]; @@ -1078,11 +1236,12 @@ free_wrb_handle(struct beiscsi_hba *phba, struct hwi_wrb_context *pwrb_context,  	else  		pwrb_context->free_index++; -	SE_DEBUG(DBG_LVL_8, -		 "FREE WRB: pwrb_handle=%p free_index=0x%x" -		 "wrb_handles_available=%d\n", -		 pwrb_handle, pwrb_context->free_index, -		 pwrb_context->wrb_handles_available); +	beiscsi_log(phba, KERN_INFO, +		    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +		    "BM_%d : FREE WRB: pwrb_handle=%p free_index=0x%x" +		    "wrb_handles_available=%d\n", +		    pwrb_handle, pwrb_context->free_index, +		    pwrb_context->wrb_handles_available);  }  static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba) @@ -1092,8 +1251,11 @@ static struct sgl_handle *alloc_mgmt_sgl_handle(struct beiscsi_hba *phba)  	if (phba->eh_sgl_hndl_avbl) {  		psgl_handle = phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index];  		phba->eh_sgl_hndl_base[phba->eh_sgl_alloc_index] = NULL; -		SE_DEBUG(DBG_LVL_8, "mgmt_sgl_alloc_index=%d=0x%x\n", -			 phba->eh_sgl_alloc_index, phba->eh_sgl_alloc_index); +		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, +			    "BM_%d : mgmt_sgl_alloc_index=%d=0x%x\n", +			    phba->eh_sgl_alloc_index, +			    phba->eh_sgl_alloc_index); +  		phba->eh_sgl_hndl_avbl--;  		if (phba->eh_sgl_alloc_index ==  		    (phba->params.icds_per_ctrl - phba->params.ios_per_ctrl - @@ -1110,16 +1272,20 @@ void  free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)  { -	SE_DEBUG(DBG_LVL_8, "In  free_mgmt_sgl_handle,eh_sgl_free_index=%d\n", -			     phba->eh_sgl_free_index); +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_CONFIG, +		    "BM_%d : In  free_mgmt_sgl_handle," +		    "eh_sgl_free_index=%d\n", +		    phba->eh_sgl_free_index); +  	if (phba->eh_sgl_hndl_base[phba->eh_sgl_free_index]) {  		/*  		 * this can happen if clean_task is called on a task that  		 * failed in xmit_task or alloc_pdu.  		 */ -		SE_DEBUG(DBG_LVL_8, -			 "Double Free in eh SGL ,eh_sgl_free_index=%d\n", -			 phba->eh_sgl_free_index); +		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, +			    "BM_%d : Double Free in eh SGL ," +			    "eh_sgl_free_index=%d\n", +			    phba->eh_sgl_free_index);  		return;  	}  	phba->eh_sgl_hndl_base[phba->eh_sgl_free_index] = psgl_handle; @@ -1133,32 +1299,33 @@ free_mgmt_sgl_handle(struct beiscsi_hba *phba, struct sgl_handle *psgl_handle)  static void  be_complete_io(struct beiscsi_conn *beiscsi_conn, -	       struct iscsi_task *task, struct sol_cqe *psol) +		struct iscsi_task *task, +		struct common_sol_cqe *csol_cqe)  {  	struct beiscsi_io_task *io_task = task->dd_data;  	struct be_status_bhs *sts_bhs =  				(struct be_status_bhs *)io_task->cmd_bhs;  	struct iscsi_conn *conn = beiscsi_conn->conn; -	unsigned int sense_len;  	unsigned char *sense;  	u32 resid = 0, exp_cmdsn, max_cmdsn;  	u8 rsp, status, flags; -	exp_cmdsn = (psol-> -			dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] -			& SOL_EXP_CMD_SN_MASK); -	max_cmdsn = ((psol-> -			dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] -			& SOL_EXP_CMD_SN_MASK) + -			((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) -				/ 32] & SOL_CMD_WND_MASK) >> 24) - 1); -	rsp = ((psol->dw[offsetof(struct amap_sol_cqe, i_resp) / 32] -						& SOL_RESP_MASK) >> 16); -	status = ((psol->dw[offsetof(struct amap_sol_cqe, i_sts) / 32] -						& SOL_STS_MASK) >> 8); -	flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] -					& SOL_FLAGS_MASK) >> 24) | 0x80; +	exp_cmdsn = csol_cqe->exp_cmdsn; +	max_cmdsn = (csol_cqe->exp_cmdsn + +		     csol_cqe->cmd_wnd - 1); +	rsp = csol_cqe->i_resp; +	status = csol_cqe->i_sts; +	flags = csol_cqe->i_flags; +	resid = csol_cqe->res_cnt; + +	if (!task->sc) { +		if (io_task->scsi_cmnd) { +			scsi_dma_unmap(io_task->scsi_cmnd); +			io_task->scsi_cmnd = NULL; +		} +		return; +	}  	task->sc->result = (DID_OK << 16) | status;  	if (rsp != ISCSI_STATUS_CMD_COMPLETED) {  		task->sc->result = DID_ERROR << 16; @@ -1167,9 +1334,6 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,  	/* bidi not initially supported */  	if (flags & (ISCSI_FLAG_CMD_UNDERFLOW | ISCSI_FLAG_CMD_OVERFLOW)) { -		resid = (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / -				32] & SOL_RES_CNT_MASK); -  		if (!status && (flags & ISCSI_FLAG_CMD_OVERFLOW))  			task->sc->result = DID_ERROR << 16; @@ -1182,28 +1346,27 @@ be_complete_io(struct beiscsi_conn *beiscsi_conn,  	}  	if (status == SAM_STAT_CHECK_CONDITION) { +		u16 sense_len;  		unsigned short *slen = (unsigned short *)sts_bhs->sense_info; +  		sense = sts_bhs->sense_info + sizeof(unsigned short); -		sense_len =  cpu_to_be16(*slen); +		sense_len = be16_to_cpu(*slen);  		memcpy(task->sc->sense_buffer, sense,  		       min_t(u16, sense_len, SCSI_SENSE_BUFFERSIZE));  	} -	if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) { -		if (psol->dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] -							& SOL_RES_CNT_MASK) -			 conn->rxdata_octets += (psol-> -			     dw[offsetof(struct amap_sol_cqe, i_res_cnt) / 32] -			     & SOL_RES_CNT_MASK); -	} +	if (io_task->cmd_bhs->iscsi_hdr.flags & ISCSI_FLAG_CMD_READ) +		conn->rxdata_octets += resid;  unmap:  	scsi_dma_unmap(io_task->scsi_cmnd); +	io_task->scsi_cmnd = NULL;  	iscsi_complete_scsi_task(task, exp_cmdsn, max_cmdsn);  }  static void  be_complete_logout(struct beiscsi_conn *beiscsi_conn, -		   struct iscsi_task *task, struct sol_cqe *psol) +		    struct iscsi_task *task, +		    struct common_sol_cqe *csol_cqe)  {  	struct iscsi_logout_rsp *hdr;  	struct beiscsi_io_task *io_task = task->dd_data; @@ -1213,18 +1376,12 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,  	hdr->opcode = ISCSI_OP_LOGOUT_RSP;  	hdr->t2wait = 5;  	hdr->t2retain = 0; -	hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] -					& SOL_FLAGS_MASK) >> 24) | 0x80; -	hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) / -					32] & SOL_RESP_MASK); -	hdr->exp_cmdsn = cpu_to_be32(psol-> -			dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] -					& SOL_EXP_CMD_SN_MASK); -	hdr->max_cmdsn = be32_to_cpu((psol-> -			 dw[offsetof(struct amap_sol_cqe, i_exp_cmd_sn) / 32] -					& SOL_EXP_CMD_SN_MASK) + -			((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) -					/ 32] & SOL_CMD_WND_MASK) >> 24) - 1); +	hdr->flags = csol_cqe->i_flags; +	hdr->response = csol_cqe->i_resp; +	hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); +	hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn + +				     csol_cqe->cmd_wnd - 1); +  	hdr->dlength[0] = 0;  	hdr->dlength[1] = 0;  	hdr->dlength[2] = 0; @@ -1235,7 +1392,8 @@ be_complete_logout(struct beiscsi_conn *beiscsi_conn,  static void  be_complete_tmf(struct beiscsi_conn *beiscsi_conn, -		struct iscsi_task *task, struct sol_cqe *psol) +		 struct iscsi_task *task, +		 struct common_sol_cqe *csol_cqe)  {  	struct iscsi_tm_rsp *hdr;  	struct iscsi_conn *conn = beiscsi_conn->conn; @@ -1243,16 +1401,12 @@ be_complete_tmf(struct beiscsi_conn *beiscsi_conn,  	hdr = (struct iscsi_tm_rsp *)task->hdr;  	hdr->opcode = ISCSI_OP_SCSI_TMFUNC_RSP; -	hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] -					& SOL_FLAGS_MASK) >> 24) | 0x80; -	hdr->response = (psol->dw[offsetof(struct amap_sol_cqe, i_resp) / -					32] & SOL_RESP_MASK); -	hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe, -				    i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK); -	hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe, -			i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) + -			((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) -			/ 32] & SOL_CMD_WND_MASK) >> 24) - 1); +	hdr->flags = csol_cqe->i_flags; +	hdr->response = csol_cqe->i_resp; +	hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); +	hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn + +				     csol_cqe->cmd_wnd - 1); +  	hdr->itt = io_task->libiscsi_itt;  	__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);  } @@ -1266,50 +1420,105 @@ hwi_complete_drvr_msgs(struct beiscsi_conn *beiscsi_conn,  	struct hwi_controller *phwi_ctrlr;  	struct iscsi_task *task;  	struct beiscsi_io_task *io_task; -	struct iscsi_conn *conn = beiscsi_conn->conn; -	struct iscsi_session *session = conn->session; +	uint16_t wrb_index, cid, cri_index;  	phwi_ctrlr = phba->phwi_ctrlr; -	pwrb_context = &phwi_ctrlr->wrb_context[((psol-> -				dw[offsetof(struct amap_sol_cqe, cid) / 32] & -				SOL_CID_MASK) >> 6) - -				phba->fw_config.iscsi_cid_start]; -	pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> -				dw[offsetof(struct amap_sol_cqe, wrb_index) / -				32] & SOL_WRB_INDEX_MASK) >> 16)]; +	if (is_chip_be2_be3r(phba)) { +		wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe, +					  wrb_idx, psol); +		cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe, +				    cid, psol); +	} else { +		wrb_index = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, +					  wrb_idx, psol); +		cid = AMAP_GET_BITS(struct amap_it_dmsg_cqe_v2, +				    cid, psol); +	} + +	cri_index = BE_GET_CRI_FROM_CID(cid); +	pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; +	pwrb_handle = pwrb_context->pwrb_handle_basestd[wrb_index];  	task = pwrb_handle->pio_handle;  	io_task = task->dd_data; -	spin_lock(&phba->mgmt_sgl_lock); -	free_mgmt_sgl_handle(phba, io_task->psgl_handle); -	spin_unlock(&phba->mgmt_sgl_lock); -	spin_lock_bh(&session->lock); -	free_wrb_handle(phba, pwrb_context, pwrb_handle); -	spin_unlock_bh(&session->lock); +	memset(io_task->pwrb_handle->pwrb, 0, sizeof(struct iscsi_wrb)); +	iscsi_put_task(task);  }  static void  be_complete_nopin_resp(struct beiscsi_conn *beiscsi_conn, -		       struct iscsi_task *task, struct sol_cqe *psol) +			struct iscsi_task *task, +			struct common_sol_cqe *csol_cqe)  {  	struct iscsi_nopin *hdr;  	struct iscsi_conn *conn = beiscsi_conn->conn;  	struct beiscsi_io_task *io_task = task->dd_data;  	hdr = (struct iscsi_nopin *)task->hdr; -	hdr->flags = ((psol->dw[offsetof(struct amap_sol_cqe, i_flags) / 32] -			& SOL_FLAGS_MASK) >> 24) | 0x80; -	hdr->exp_cmdsn = cpu_to_be32(psol->dw[offsetof(struct amap_sol_cqe, -				     i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK); -	hdr->max_cmdsn = be32_to_cpu((psol->dw[offsetof(struct amap_sol_cqe, -			i_exp_cmd_sn) / 32] & SOL_EXP_CMD_SN_MASK) + -			((psol->dw[offsetof(struct amap_sol_cqe, i_cmd_wnd) -			/ 32] & SOL_CMD_WND_MASK) >> 24) - 1); +	hdr->flags = csol_cqe->i_flags; +	hdr->exp_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn); +	hdr->max_cmdsn = cpu_to_be32(csol_cqe->exp_cmdsn + +				     csol_cqe->cmd_wnd - 1); +  	hdr->opcode = ISCSI_OP_NOOP_IN;  	hdr->itt = io_task->libiscsi_itt;  	__iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, NULL, 0);  } +static void adapter_get_sol_cqe(struct beiscsi_hba *phba, +		struct sol_cqe *psol, +		struct common_sol_cqe *csol_cqe) +{ +	if (is_chip_be2_be3r(phba)) { +		csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe, +						    i_exp_cmd_sn, psol); +		csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe, +						  i_res_cnt, psol); +		csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe, +						  i_cmd_wnd, psol); +		csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe, +						    wrb_index, psol); +		csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe, +					      cid, psol); +		csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe, +						 hw_sts, psol); +		csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe, +						 i_resp, psol); +		csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe, +						i_sts, psol); +		csol_cqe->i_flags = AMAP_GET_BITS(struct amap_sol_cqe, +						  i_flags, psol); +	} else { +		csol_cqe->exp_cmdsn = AMAP_GET_BITS(struct amap_sol_cqe_v2, +						    i_exp_cmd_sn, psol); +		csol_cqe->res_cnt = AMAP_GET_BITS(struct amap_sol_cqe_v2, +						  i_res_cnt, psol); +		csol_cqe->wrb_index = AMAP_GET_BITS(struct amap_sol_cqe_v2, +						    wrb_index, psol); +		csol_cqe->cid = AMAP_GET_BITS(struct amap_sol_cqe_v2, +					      cid, psol); +		csol_cqe->hw_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2, +						 hw_sts, psol); +		csol_cqe->cmd_wnd = AMAP_GET_BITS(struct amap_sol_cqe_v2, +						  i_cmd_wnd, psol); +		if (AMAP_GET_BITS(struct amap_sol_cqe_v2, +				  cmd_cmpl, psol)) +			csol_cqe->i_sts = AMAP_GET_BITS(struct amap_sol_cqe_v2, +							i_sts, psol); +		else +			csol_cqe->i_resp = AMAP_GET_BITS(struct amap_sol_cqe_v2, +							 i_sts, psol); +		if (AMAP_GET_BITS(struct amap_sol_cqe_v2, +				  u, psol)) +			csol_cqe->i_flags = ISCSI_FLAG_CMD_UNDERFLOW; + +		if (AMAP_GET_BITS(struct amap_sol_cqe_v2, +				  o, psol)) +			csol_cqe->i_flags |= ISCSI_FLAG_CMD_OVERFLOW; +	} +} + +  static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,  			     struct beiscsi_hba *phba, struct sol_cqe *psol)  { @@ -1321,61 +1530,64 @@ static void hwi_complete_cmd(struct beiscsi_conn *beiscsi_conn,  	unsigned int type;  	struct iscsi_conn *conn = beiscsi_conn->conn;  	struct iscsi_session *session = conn->session; +	struct common_sol_cqe csol_cqe = {0}; +	uint16_t cri_index = 0;  	phwi_ctrlr = phba->phwi_ctrlr; -	pwrb_context = &phwi_ctrlr->wrb_context[((psol->dw[offsetof -				(struct amap_sol_cqe, cid) / 32] -				& SOL_CID_MASK) >> 6) - -				phba->fw_config.iscsi_cid_start]; -	pwrb_handle = pwrb_context->pwrb_handle_basestd[((psol-> -				dw[offsetof(struct amap_sol_cqe, wrb_index) / -				32] & SOL_WRB_INDEX_MASK) >> 16)]; + +	/* Copy the elements to a common structure */ +	adapter_get_sol_cqe(phba, psol, &csol_cqe); + +	cri_index = BE_GET_CRI_FROM_CID(csol_cqe.cid); +	pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; + +	pwrb_handle = pwrb_context->pwrb_handle_basestd[ +		      csol_cqe.wrb_index]; +  	task = pwrb_handle->pio_handle;  	pwrb = pwrb_handle->pwrb; -	type = (pwrb->dw[offsetof(struct amap_iscsi_wrb, type) / 32] & -				 WRB_TYPE_MASK) >> 28; +	type = ((struct beiscsi_io_task *)task->dd_data)->wrb_type; -	spin_lock_bh(&session->lock); +	spin_lock_bh(&session->back_lock);  	switch (type) {  	case HWH_TYPE_IO:  	case HWH_TYPE_IO_RD:  		if ((task->hdr->opcode & ISCSI_OPCODE_MASK) ==  		     ISCSI_OP_NOOP_OUT) -			be_complete_nopin_resp(beiscsi_conn, task, psol); +			be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe);  		else -			be_complete_io(beiscsi_conn, task, psol); +			be_complete_io(beiscsi_conn, task, &csol_cqe);  		break;  	case HWH_TYPE_LOGOUT:  		if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGOUT) -			be_complete_logout(beiscsi_conn, task, psol); +			be_complete_logout(beiscsi_conn, task, &csol_cqe);  		else -			be_complete_tmf(beiscsi_conn, task, psol); - +			be_complete_tmf(beiscsi_conn, task, &csol_cqe);  		break;  	case HWH_TYPE_LOGIN: -		SE_DEBUG(DBG_LVL_1, -			 "\t\t No HWH_TYPE_LOGIN Expected in hwi_complete_cmd" -			 "- Solicited path\n"); +		beiscsi_log(phba, KERN_ERR, +			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, +			    "BM_%d :\t\t No HWH_TYPE_LOGIN Expected in" +			    " hwi_complete_cmd- Solicited path\n");  		break;  	case HWH_TYPE_NOP: -		be_complete_nopin_resp(beiscsi_conn, task, psol); +		be_complete_nopin_resp(beiscsi_conn, task, &csol_cqe);  		break;  	default: -		shost_printk(KERN_WARNING, phba->shost, -				"In hwi_complete_cmd, unknown type = %d" -				"wrb_index 0x%x CID 0x%x\n", type, -				((psol->dw[offsetof(struct amap_iscsi_wrb, -				type) / 32] & SOL_WRB_INDEX_MASK) >> 16), -				((psol->dw[offsetof(struct amap_sol_cqe, -				cid) / 32] & SOL_CID_MASK) >> 6)); +		beiscsi_log(phba, KERN_WARNING, +			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, +			    "BM_%d : In hwi_complete_cmd, unknown type = %d" +			    "wrb_index 0x%x CID 0x%x\n", type, +			    csol_cqe.wrb_index, +			    csol_cqe.cid);  		break;  	} -	spin_unlock_bh(&session->lock); +	spin_unlock_bh(&session->back_lock);  }  static struct list_head *hwi_get_async_busy_list(struct hwi_async_pdu_context @@ -1398,16 +1610,27 @@ hwi_get_async_handle(struct beiscsi_hba *phba,  	struct be_bus_address phys_addr;  	struct list_head *pbusy_list;  	struct async_pdu_handle *pasync_handle = NULL; -	int buffer_len = 0; -	unsigned char buffer_index = -1;  	unsigned char is_header = 0; +	unsigned int index, dpl; + +	if (is_chip_be2_be3r(phba)) { +		dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, +				    dpl, pdpdu_cqe); +		index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe, +				      index, pdpdu_cqe); +	} else { +		dpl = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, +				    dpl, pdpdu_cqe); +		index = AMAP_GET_BITS(struct amap_i_t_dpdu_cqe_v2, +				      index, pdpdu_cqe); +	}  	phys_addr.u.a32.address_lo = -	    pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_lo) / 32] - -	    ((pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32] -						& PDUCQE_DPL_MASK) >> 16); +		(pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, +					db_addr_lo) / 32] - dpl);  	phys_addr.u.a32.address_hi = -	    pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, db_addr_hi) / 32]; +		pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, +				       db_addr_hi) / 32];  	phys_addr.u.a64.address =  			*((unsigned long long *)(&phys_addr.u.a64.address)); @@ -1417,75 +1640,57 @@ hwi_get_async_handle(struct beiscsi_hba *phba,  	case UNSOL_HDR_NOTIFY:  		is_header = 1; -		pbusy_list = hwi_get_async_busy_list(pasync_ctx, 1, -			(pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, -			index) / 32] & PDUCQE_INDEX_MASK)); - -		buffer_len = (unsigned int)(phys_addr.u.a64.address - -				pasync_ctx->async_header.pa_base.u.a64.address); - -		buffer_index = buffer_len / -				pasync_ctx->async_header.buffer_size; - +		 pbusy_list = hwi_get_async_busy_list(pasync_ctx, +						      is_header, index);  		break;  	case UNSOL_DATA_NOTIFY: -		pbusy_list = hwi_get_async_busy_list(pasync_ctx, 0, (pdpdu_cqe-> -					dw[offsetof(struct amap_i_t_dpdu_cqe, -					index) / 32] & PDUCQE_INDEX_MASK)); -		buffer_len = (unsigned long)(phys_addr.u.a64.address - -					pasync_ctx->async_data.pa_base.u. -					a64.address); -		buffer_index = buffer_len / pasync_ctx->async_data.buffer_size; +		 pbusy_list = hwi_get_async_busy_list(pasync_ctx, +						      is_header, index);  		break;  	default:  		pbusy_list = NULL; -		shost_printk(KERN_WARNING, phba->shost, -			"Unexpected code=%d\n", -			 pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, -					code) / 32] & PDUCQE_CODE_MASK); +		beiscsi_log(phba, KERN_WARNING, +			    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +			    "BM_%d : Unexpected code=%d\n", +			    pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, +			    code) / 32] & PDUCQE_CODE_MASK);  		return NULL;  	} -	WARN_ON(!(buffer_index <= pasync_ctx->async_data.num_entries));  	WARN_ON(list_empty(pbusy_list));  	list_for_each_entry(pasync_handle, pbusy_list, link) { -		WARN_ON(pasync_handle->consumed); -		if (pasync_handle->index == buffer_index) +		if (pasync_handle->pa.u.a64.address == phys_addr.u.a64.address)  			break;  	}  	WARN_ON(!pasync_handle); -	pasync_handle->cri = (unsigned short)beiscsi_conn->beiscsi_conn_cid - -					     phba->fw_config.iscsi_cid_start; +	pasync_handle->cri = BE_GET_ASYNC_CRI_FROM_CID( +			     beiscsi_conn->beiscsi_conn_cid);  	pasync_handle->is_header = is_header; -	pasync_handle->buffer_len = ((pdpdu_cqe-> -			dw[offsetof(struct amap_i_t_dpdu_cqe, dpl) / 32] -			& PDUCQE_DPL_MASK) >> 16); +	pasync_handle->buffer_len = dpl; +	*pcq_index = index; -	*pcq_index = (pdpdu_cqe->dw[offsetof(struct amap_i_t_dpdu_cqe, -			index) / 32] & PDUCQE_INDEX_MASK);  	return pasync_handle;  }  static unsigned int -hwi_update_async_writables(struct hwi_async_pdu_context *pasync_ctx, -			   unsigned int is_header, unsigned int cq_index) +hwi_update_async_writables(struct beiscsi_hba *phba, +			    struct hwi_async_pdu_context *pasync_ctx, +			    unsigned int is_header, unsigned int cq_index)  {  	struct list_head *pbusy_list;  	struct async_pdu_handle *pasync_handle;  	unsigned int num_entries, writables = 0;  	unsigned int *pep_read_ptr, *pwritables; - +	num_entries = pasync_ctx->num_entries;  	if (is_header) {  		pep_read_ptr = &pasync_ctx->async_header.ep_read_ptr;  		pwritables = &pasync_ctx->async_header.writables; -		num_entries = pasync_ctx->async_header.num_entries;  	} else {  		pep_read_ptr = &pasync_ctx->async_data.ep_read_ptr;  		pwritables = &pasync_ctx->async_data.writables; -		num_entries = pasync_ctx->async_data.num_entries;  	}  	while ((*pep_read_ptr) != cq_index) { @@ -1509,9 +1714,10 @@ hwi_update_async_writables(struct hwi_async_pdu_context *pasync_ctx,  	}  	if (!writables) { -		SE_DEBUG(DBG_LVL_1, -			 "Duplicate notification received - index 0x%x!!\n", -			 cq_index); +		beiscsi_log(phba, KERN_ERR, +			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, +			    "BM_%d : Duplicate notification received - index 0x%x!!\n", +			    cq_index);  		WARN_ON(1);  	} @@ -1519,40 +1725,31 @@ hwi_update_async_writables(struct hwi_async_pdu_context *pasync_ctx,  	return 0;  } -static unsigned int hwi_free_async_msg(struct beiscsi_hba *phba, -				       unsigned int cri) +static void hwi_free_async_msg(struct beiscsi_hba *phba, +			       struct hwi_async_pdu_context *pasync_ctx, +			       unsigned int cri)  { -	struct hwi_controller *phwi_ctrlr; -	struct hwi_async_pdu_context *pasync_ctx;  	struct async_pdu_handle *pasync_handle, *tmp_handle;  	struct list_head *plist; -	unsigned int i = 0; - -	phwi_ctrlr = phba->phwi_ctrlr; -	pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr);  	plist  = &pasync_ctx->async_entry[cri].wait_queue.list; -  	list_for_each_entry_safe(pasync_handle, tmp_handle, plist, link) {  		list_del(&pasync_handle->link); -		if (i == 0) { +		if (pasync_handle->is_header) {  			list_add_tail(&pasync_handle->link,  				      &pasync_ctx->async_header.free_list);  			pasync_ctx->async_header.free_entries++; -			i++;  		} else {  			list_add_tail(&pasync_handle->link,  				      &pasync_ctx->async_data.free_list);  			pasync_ctx->async_data.free_entries++; -			i++;  		}  	}  	INIT_LIST_HEAD(&pasync_ctx->async_entry[cri].wait_queue.list);  	pasync_ctx->async_entry[cri].wait_queue.hdr_received = 0;  	pasync_ctx->async_entry[cri].wait_queue.bytes_received = 0; -	return 0;  }  static struct phys_addr * @@ -1570,7 +1767,7 @@ hwi_get_ring_address(struct hwi_async_pdu_context *pasync_ctx,  }  static void hwi_post_async_buffers(struct beiscsi_hba *phba, -				   unsigned int is_header) +				    unsigned int is_header, uint8_t ulp_num)  {  	struct hwi_controller *phwi_ctrlr;  	struct hwi_async_pdu_context *pasync_ctx; @@ -1578,28 +1775,31 @@ static void hwi_post_async_buffers(struct beiscsi_hba *phba,  	struct list_head *pfree_link, *pbusy_list;  	struct phys_addr *pasync_sge;  	unsigned int ring_id, num_entries; -	unsigned int host_write_num; +	unsigned int host_write_num, doorbell_offset;  	unsigned int writables;  	unsigned int i = 0;  	u32 doorbell = 0;  	phwi_ctrlr = phba->phwi_ctrlr; -	pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); +	pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, ulp_num); +	num_entries = pasync_ctx->num_entries;  	if (is_header) { -		num_entries = pasync_ctx->async_header.num_entries;  		writables = min(pasync_ctx->async_header.writables,  				pasync_ctx->async_header.free_entries);  		pfree_link = pasync_ctx->async_header.free_list.next;  		host_write_num = pasync_ctx->async_header.host_write_ptr; -		ring_id = phwi_ctrlr->default_pdu_hdr.id; +		ring_id = phwi_ctrlr->default_pdu_hdr[ulp_num].id; +		doorbell_offset = phwi_ctrlr->default_pdu_hdr[ulp_num]. +				  doorbell_offset;  	} else { -		num_entries = pasync_ctx->async_data.num_entries;  		writables = min(pasync_ctx->async_data.writables,  				pasync_ctx->async_data.free_entries);  		pfree_link = pasync_ctx->async_data.free_list.next;  		host_write_num = pasync_ctx->async_data.host_write_ptr; -		ring_id = phwi_ctrlr->default_pdu_data.id; +		ring_id = phwi_ctrlr->default_pdu_data[ulp_num].id; +		doorbell_offset = phwi_ctrlr->default_pdu_data[ulp_num]. +				  doorbell_offset;  	}  	writables = (writables / 8) * 8; @@ -1647,7 +1847,7 @@ static void hwi_post_async_buffers(struct beiscsi_hba *phba,  		doorbell |= (writables & DB_DEF_PDU_CQPROC_MASK)  					<< DB_DEF_PDU_CQPROC_SHIFT; -		iowrite32(doorbell, phba->db_va + DB_RXULP0_OFFSET); +		iowrite32(doorbell, phba->db_va + doorbell_offset);  	}  } @@ -1659,19 +1859,25 @@ static void hwi_flush_default_pdu_buffer(struct beiscsi_hba *phba,  	struct hwi_async_pdu_context *pasync_ctx;  	struct async_pdu_handle *pasync_handle = NULL;  	unsigned int cq_index = -1; +	uint16_t cri_index = BE_GET_CRI_FROM_CID( +			     beiscsi_conn->beiscsi_conn_cid);  	phwi_ctrlr = phba->phwi_ctrlr; -	pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); +	pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, +		     BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, +		     cri_index));  	pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx,  					     pdpdu_cqe, &cq_index);  	BUG_ON(pasync_handle->is_header != 0);  	if (pasync_handle->consumed == 0) -		hwi_update_async_writables(pasync_ctx, pasync_handle->is_header, -					   cq_index); +		hwi_update_async_writables(phba, pasync_ctx, +					   pasync_handle->is_header, cq_index); -	hwi_free_async_msg(phba, pasync_handle->cri); -	hwi_post_async_buffers(phba, pasync_handle->is_header); +	hwi_free_async_msg(phba, pasync_ctx, pasync_handle->cri); +	hwi_post_async_buffers(phba, pasync_handle->is_header, +			       BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, +			       cri_index));  }  static unsigned int @@ -1701,19 +1907,16 @@ hwi_fwd_async_msg(struct beiscsi_conn *beiscsi_conn,  			}  			memcpy(pfirst_buffer + offset,  			       pasync_handle->pbuffer, buf_len); -			offset = buf_len; +			offset += buf_len;  		}  		index++;  	}  	status = beiscsi_process_async_pdu(beiscsi_conn, phba, -					   (beiscsi_conn->beiscsi_conn_cid - -					    phba->fw_config.iscsi_cid_start),  					    phdr, hdr_len, pfirst_buffer, -					    buf_len); +					    offset); -	if (status == 0) -		hwi_free_async_msg(phba, cri); +	hwi_free_async_msg(phba, pasync_ctx, cri);  	return 0;  } @@ -1729,13 +1932,16 @@ hwi_gather_async_pdu(struct beiscsi_conn *beiscsi_conn,  	struct pdu_base *ppdu;  	phwi_ctrlr = phba->phwi_ctrlr; -	pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); +	pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, +		     BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, +		     BE_GET_CRI_FROM_CID(beiscsi_conn-> +				 beiscsi_conn_cid)));  	list_del(&pasync_handle->link);  	if (pasync_handle->is_header) {  		pasync_ctx->async_header.busy_entries--;  		if (pasync_ctx->async_entry[cri].wait_queue.hdr_received) { -			hwi_free_async_msg(phba, cri); +			hwi_free_async_msg(phba, pasync_ctx, cri);  			BUG();  		} @@ -1790,17 +1996,25 @@ static void hwi_process_default_pdu_ring(struct beiscsi_conn *beiscsi_conn,  	struct hwi_async_pdu_context *pasync_ctx;  	struct async_pdu_handle *pasync_handle = NULL;  	unsigned int cq_index = -1; +	uint16_t cri_index = BE_GET_CRI_FROM_CID( +			     beiscsi_conn->beiscsi_conn_cid);  	phwi_ctrlr = phba->phwi_ctrlr; -	pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr); +	pasync_ctx = HWI_GET_ASYNC_PDU_CTX(phwi_ctrlr, +		     BEISCSI_GET_ULP_FROM_CRI(phwi_ctrlr, +		     cri_index)); +  	pasync_handle = hwi_get_async_handle(phba, beiscsi_conn, pasync_ctx,  					     pdpdu_cqe, &cq_index);  	if (pasync_handle->consumed == 0) -		hwi_update_async_writables(pasync_ctx, pasync_handle->is_header, -					   cq_index); +		hwi_update_async_writables(phba, pasync_ctx, +					   pasync_handle->is_header, cq_index); +  	hwi_gather_async_pdu(beiscsi_conn, phba, pasync_handle); -	hwi_post_async_buffers(phba, pasync_handle->is_header); +	hwi_post_async_buffers(phba, pasync_handle->is_header, +			       BEISCSI_GET_ULP_FROM_CRI( +			       phwi_ctrlr, cri_index));  }  static void  beiscsi_process_mcc_isr(struct beiscsi_hba *phba) @@ -1826,9 +2040,10 @@ static void  beiscsi_process_mcc_isr(struct beiscsi_hba *phba)  				beiscsi_async_link_state_process(phba,  				(struct be_async_event_link_state *) mcc_compl);  			else -				SE_DEBUG(DBG_LVL_1, -					" Unsupported Async Event, flags" -					" = 0x%08x\n", mcc_compl->flags); +				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_MBOX, +					    "BM_%d :  Unsupported Async Event, flags" +					    " = 0x%08x\n", +					    mcc_compl->flags);  		} else if (mcc_compl->flags & CQE_FLAGS_COMPLETED_MASK) {  			be_mcc_compl_process_isr(&phba->ctrl, mcc_compl);  			atomic_dec(&phba->ctrl.mcc_obj.q.used); @@ -1846,6 +2061,13 @@ static void  beiscsi_process_mcc_isr(struct beiscsi_hba *phba)  } +/** + * beiscsi_process_cq()- Process the Completion Queue + * @pbe_eq: Event Q on which the Completion has come + * + * return + *     Number of Completion Entries processed. + **/  static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)  {  	struct be_queue_info *cq; @@ -1853,6 +2075,8 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)  	struct dmsg_cqe *dmsg;  	unsigned int num_processed = 0;  	unsigned int tot_nump = 0; +	unsigned short code = 0, cid = 0; +	uint16_t cri_index = 0;  	struct beiscsi_conn *beiscsi_conn;  	struct beiscsi_endpoint *beiscsi_ep;  	struct iscsi_endpoint *ep; @@ -1866,11 +2090,26 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)  	       CQE_VALID_MASK) {  		be_dws_le_to_cpu(sol, sizeof(struct sol_cqe)); -		ep = phba->ep_array[(u32) ((sol-> -				   dw[offsetof(struct amap_sol_cqe, cid) / 32] & -				   SOL_CID_MASK) >> 6) - -				   phba->fw_config.iscsi_cid_start]; +		 code = (sol->dw[offsetof(struct amap_sol_cqe, code) / +			 32] & CQE_CODE_MASK); + +		 /* Get the CID */ +		if (is_chip_be2_be3r(phba)) { +			cid = AMAP_GET_BITS(struct amap_sol_cqe, cid, sol); +		} else { +			if ((code == DRIVERMSG_NOTIFY) || +			    (code == UNSOL_HDR_NOTIFY) || +			    (code == UNSOL_DATA_NOTIFY)) +				cid = AMAP_GET_BITS( +						    struct amap_i_t_dpdu_cqe_v2, +						    cid, sol); +			 else +				 cid = AMAP_GET_BITS(struct amap_sol_cqe_v2, +						     cid, sol); +		} +		cri_index = BE_GET_CRI_FROM_CID(cid); +		ep = phba->ep_array[cri_index];  		beiscsi_ep = ep->dd_data;  		beiscsi_conn = beiscsi_ep->conn; @@ -1881,32 +2120,48 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)  			num_processed = 0;  		} -		switch ((u32) sol->dw[offsetof(struct amap_sol_cqe, code) / -			32] & CQE_CODE_MASK) { +		switch (code) {  		case SOL_CMD_COMPLETE:  			hwi_complete_cmd(beiscsi_conn, phba, sol);  			break;  		case DRIVERMSG_NOTIFY: -			SE_DEBUG(DBG_LVL_8, "Received DRIVERMSG_NOTIFY\n"); +			beiscsi_log(phba, KERN_INFO, +				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +				    "BM_%d : Received %s[%d] on CID : %d\n", +				    cqe_desc[code], code, cid); +  			dmsg = (struct dmsg_cqe *)sol;  			hwi_complete_drvr_msgs(beiscsi_conn, phba, sol);  			break;  		case UNSOL_HDR_NOTIFY: -			SE_DEBUG(DBG_LVL_8, "Received UNSOL_HDR_ NOTIFY\n"); +			beiscsi_log(phba, KERN_INFO, +				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +				    "BM_%d : Received %s[%d] on CID : %d\n", +				    cqe_desc[code], code, cid); + +			spin_lock_bh(&phba->async_pdu_lock);  			hwi_process_default_pdu_ring(beiscsi_conn, phba,  					     (struct i_t_dpdu_cqe *)sol); +			spin_unlock_bh(&phba->async_pdu_lock);  			break;  		case UNSOL_DATA_NOTIFY: -			SE_DEBUG(DBG_LVL_8, "Received UNSOL_DATA_NOTIFY\n"); +			beiscsi_log(phba, KERN_INFO, +				    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, +				    "BM_%d : Received %s[%d] on CID : %d\n", +				    cqe_desc[code], code, cid); + +			spin_lock_bh(&phba->async_pdu_lock);  			hwi_process_default_pdu_ring(beiscsi_conn, phba,  					     (struct i_t_dpdu_cqe *)sol); +			spin_unlock_bh(&phba->async_pdu_lock);  			break;  		case CXN_INVALIDATE_INDEX_NOTIFY:  		case CMD_INVALIDATED_NOTIFY:  		case CXN_INVALIDATE_NOTIFY: -			SE_DEBUG(DBG_LVL_1, -				 "Ignoring CQ Error notification for cmd/cxn" -				 "invalidate\n"); +			beiscsi_log(phba, KERN_ERR, +				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +				    "BM_%d : Ignoring %s[%d] on CID : %d\n", +				    cqe_desc[code], code, cid);  			break;  		case SOL_CMD_KILLED_DATA_DIGEST_ERR:  		case CMD_KILLED_INVALID_STATSN_RCVD: @@ -1916,19 +2171,20 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)  		case CMD_CXN_KILLED_ITT_INVALID:  		case CMD_CXN_KILLED_SEQ_OUTOFORDER:  		case CMD_CXN_KILLED_INVALID_DATASN_RCVD: -			SE_DEBUG(DBG_LVL_1, -				 "CQ Error notification for cmd.. " -				 "code %d cid 0x%x\n", -				 sol->dw[offsetof(struct amap_sol_cqe, code) / -				 32] & CQE_CODE_MASK, -				 (sol->dw[offsetof(struct amap_sol_cqe, cid) / -				 32] & SOL_CID_MASK)); +			beiscsi_log(phba, KERN_ERR, +				    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, +				    "BM_%d : Cmd Notification %s[%d] on CID : %d\n", +				    cqe_desc[code], code,  cid);  			break;  		case UNSOL_DATA_DIGEST_ERROR_NOTIFY: -			SE_DEBUG(DBG_LVL_1, -				 "Digest error on def pdu ring, dropping..\n"); +			beiscsi_log(phba, KERN_ERR, +				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +				    "BM_%d :  Dropping %s[%d] on DPDU ring on CID : %d\n", +				    cqe_desc[code], code, cid); +			spin_lock_bh(&phba->async_pdu_lock);  			hwi_flush_default_pdu_buffer(phba, beiscsi_conn,  					     (struct i_t_dpdu_cqe *) sol); +			spin_unlock_bh(&phba->async_pdu_lock);  			break;  		case CXN_KILLED_PDU_SIZE_EXCEEDS_DSL:  		case CXN_KILLED_BURST_LEN_MISMATCH: @@ -1939,38 +2195,27 @@ static unsigned int beiscsi_process_cq(struct be_eq_obj *pbe_eq)  		case CXN_KILLED_INVALID_ITT_TTT_RCVD:  		case CXN_KILLED_TIMED_OUT:  		case CXN_KILLED_FIN_RCVD: +		case CXN_KILLED_RST_SENT: +		case CXN_KILLED_RST_RCVD:  		case CXN_KILLED_BAD_UNSOL_PDU_RCVD:  		case CXN_KILLED_BAD_WRB_INDEX_ERROR:  		case CXN_KILLED_OVER_RUN_RESIDUAL:  		case CXN_KILLED_UNDER_RUN_RESIDUAL:  		case CXN_KILLED_CMND_DATA_NOT_ON_SAME_CONN: -			SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset CID " -				 "0x%x...\n", -				 sol->dw[offsetof(struct amap_sol_cqe, code) / -				 32] & CQE_CODE_MASK, -				 (sol->dw[offsetof(struct amap_sol_cqe, cid) / -				 32] & CQE_CID_MASK)); -			iscsi_conn_failure(beiscsi_conn->conn, -					   ISCSI_ERR_CONN_FAILED); -			break; -		case CXN_KILLED_RST_SENT: -		case CXN_KILLED_RST_RCVD: -			SE_DEBUG(DBG_LVL_1, "CQ Error %d, reset" -				"received/sent on CID 0x%x...\n", -				 sol->dw[offsetof(struct amap_sol_cqe, code) / -				 32] & CQE_CODE_MASK, -				 (sol->dw[offsetof(struct amap_sol_cqe, cid) / -				 32] & CQE_CID_MASK)); -			iscsi_conn_failure(beiscsi_conn->conn, -					   ISCSI_ERR_CONN_FAILED); +			beiscsi_log(phba, KERN_ERR, +				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +				    "BM_%d : Event %s[%d] received on CID : %d\n", +				    cqe_desc[code], code, cid); +			if (beiscsi_conn) +				iscsi_conn_failure(beiscsi_conn->conn, +						   ISCSI_ERR_CONN_FAILED);  			break;  		default: -			SE_DEBUG(DBG_LVL_1, "CQ Error Invalid code= %d " -				 "received on CID 0x%x...\n", -				 sol->dw[offsetof(struct amap_sol_cqe, code) / -				 32] & CQE_CODE_MASK, -				 (sol->dw[offsetof(struct amap_sol_cqe, cid) / -				 32] & CQE_CID_MASK)); +			beiscsi_log(phba, KERN_ERR, +				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +				    "BM_%d : Invalid CQE Event Received Code : %d" +				    "CID 0x%x...\n", +				    code, cid);  			break;  		} @@ -1992,50 +2237,149 @@ void beiscsi_process_all_cqs(struct work_struct *work)  	unsigned long flags;  	struct hwi_controller *phwi_ctrlr;  	struct hwi_context_memory *phwi_context; -	struct be_eq_obj *pbe_eq; -	struct beiscsi_hba *phba = -	    container_of(work, struct beiscsi_hba, work_cqs); +	struct beiscsi_hba *phba; +	struct be_eq_obj *pbe_eq = +	    container_of(work, struct be_eq_obj, work_cqs); +	phba = pbe_eq->phba;  	phwi_ctrlr = phba->phwi_ctrlr;  	phwi_context = phwi_ctrlr->phwi_ctxt; -	if (phba->msix_enabled) -		pbe_eq = &phwi_context->be_eq[phba->num_cpus]; -	else -		pbe_eq = &phwi_context->be_eq[0]; -	if (phba->todo_mcc_cq) { +	if (pbe_eq->todo_mcc_cq) {  		spin_lock_irqsave(&phba->isr_lock, flags); -		phba->todo_mcc_cq = 0; +		pbe_eq->todo_mcc_cq = false;  		spin_unlock_irqrestore(&phba->isr_lock, flags);  		beiscsi_process_mcc_isr(phba);  	} -	if (phba->todo_cq) { +	if (pbe_eq->todo_cq) {  		spin_lock_irqsave(&phba->isr_lock, flags); -		phba->todo_cq = 0; +		pbe_eq->todo_cq = false;  		spin_unlock_irqrestore(&phba->isr_lock, flags);  		beiscsi_process_cq(pbe_eq);  	} + +	/* rearm EQ for further interrupts */ +	hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1);  }  static int be_iopoll(struct blk_iopoll *iop, int budget)  { -	static unsigned int ret; +	unsigned int ret;  	struct beiscsi_hba *phba;  	struct be_eq_obj *pbe_eq;  	pbe_eq = container_of(iop, struct be_eq_obj, iopoll);  	ret = beiscsi_process_cq(pbe_eq); +	pbe_eq->cq_count += ret;  	if (ret < budget) {  		phba = pbe_eq->phba;  		blk_iopoll_complete(iop); -		SE_DEBUG(DBG_LVL_8, "rearm pbe_eq->q.id =%d\n", pbe_eq->q.id); +		beiscsi_log(phba, KERN_INFO, +			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_IO, +			    "BM_%d : rearm pbe_eq->q.id =%d\n", +			    pbe_eq->q.id);  		hwi_ring_eq_db(phba, pbe_eq->q.id, 0, 0, 1, 1);  	}  	return ret;  }  static void +hwi_write_sgl_v2(struct iscsi_wrb *pwrb, struct scatterlist *sg, +		  unsigned int num_sg, struct beiscsi_io_task *io_task) +{ +	struct iscsi_sge *psgl; +	unsigned int sg_len, index; +	unsigned int sge_len = 0; +	unsigned long long addr; +	struct scatterlist *l_sg; +	unsigned int offset; + +	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_lo, pwrb, +		      io_task->bhs_pa.u.a32.address_lo); +	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, iscsi_bhs_addr_hi, pwrb, +		      io_task->bhs_pa.u.a32.address_hi); + +	l_sg = sg; +	for (index = 0; (index < num_sg) && (index < 2); index++, +			sg = sg_next(sg)) { +		if (index == 0) { +			sg_len = sg_dma_len(sg); +			addr = (u64) sg_dma_address(sg); +			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, +				      sge0_addr_lo, pwrb, +				      lower_32_bits(addr)); +			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, +				      sge0_addr_hi, pwrb, +				      upper_32_bits(addr)); +			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, +				      sge0_len, pwrb, +				      sg_len); +			sge_len = sg_len; +		} else { +			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_r2t_offset, +				      pwrb, sge_len); +			sg_len = sg_dma_len(sg); +			addr = (u64) sg_dma_address(sg); +			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, +				      sge1_addr_lo, pwrb, +				      lower_32_bits(addr)); +			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, +				      sge1_addr_hi, pwrb, +				      upper_32_bits(addr)); +			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, +				      sge1_len, pwrb, +				      sg_len); +		} +	} +	psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; +	memset(psgl, 0, sizeof(*psgl) * BE2_SGE); + +	AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, io_task->bhs_len - 2); + +	AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, +		      io_task->bhs_pa.u.a32.address_hi); +	AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, +		      io_task->bhs_pa.u.a32.address_lo); + +	if (num_sg == 1) { +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb, +			      1); +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb, +			      0); +	} else if (num_sg == 2) { +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb, +			      0); +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb, +			      1); +	} else { +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge0_last, pwrb, +			      0); +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sge1_last, pwrb, +			      0); +	} + +	sg = l_sg; +	psgl++; +	psgl++; +	offset = 0; +	for (index = 0; index < num_sg; index++, sg = sg_next(sg), psgl++) { +		sg_len = sg_dma_len(sg); +		addr = (u64) sg_dma_address(sg); +		AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, +			      lower_32_bits(addr)); +		AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, +			      upper_32_bits(addr)); +		AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, sg_len); +		AMAP_SET_BITS(struct amap_iscsi_sge, sge_offset, psgl, offset); +		AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 0); +		offset += sg_len; +	} +	psgl--; +	AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1); +} + +static void  hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,  	      unsigned int num_sg, struct beiscsi_io_task *io_task)  { @@ -2123,13 +2467,18 @@ hwi_write_sgl(struct iscsi_wrb *pwrb, struct scatterlist *sg,  	AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);  } +/** + * hwi_write_buffer()- Populate the WRB with task info + * @pwrb: ptr to the WRB entry + * @task: iscsi task which is to be executed + **/  static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)  {  	struct iscsi_sge *psgl; -	unsigned long long addr;  	struct beiscsi_io_task *io_task = task->dd_data;  	struct beiscsi_conn *beiscsi_conn = io_task->conn;  	struct beiscsi_hba *phba = beiscsi_conn->phba; +	uint8_t dsp_value = 0;  	io_task->bhs_len = sizeof(struct be_nonio_bhs) - 2;  	AMAP_SET_BITS(struct amap_iscsi_wrb, iscsi_bhs_addr_lo, pwrb, @@ -2138,26 +2487,38 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)  				io_task->bhs_pa.u.a32.address_hi);  	if (task->data) { -		if (task->data_count) { -			AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); -			addr = (u64) pci_map_single(phba->pcidev, -						    task->data, -						    task->data_count, 1); -		} else { -			AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); -			addr = 0; -		} + +		/* Check for the data_count */ +		dsp_value = (task->data_count) ? 1 : 0; + +		if (is_chip_be2_be3r(phba)) +			AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, +				      pwrb, dsp_value); +		else +			AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, +				      pwrb, dsp_value); + +		/* Map addr only if there is data_count */ +		if (dsp_value) { +			io_task->mtask_addr = pci_map_single(phba->pcidev, +							     task->data, +							     task->data_count, +							     PCI_DMA_TODEVICE); +			io_task->mtask_data_count = task->data_count; +		} else +			io_task->mtask_addr = 0; +  		AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_lo, pwrb, -						((u32)(addr & 0xFFFFFFFF))); +			      lower_32_bits(io_task->mtask_addr));  		AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_addr_hi, pwrb, -						((u32)(addr >> 32))); +			      upper_32_bits(io_task->mtask_addr));  		AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_len, pwrb,  						task->data_count);  		AMAP_SET_BITS(struct amap_iscsi_wrb, sge0_last, pwrb, 1);  	} else {  		AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0); -		addr = 0; +		io_task->mtask_addr = 0;  	}  	psgl = (struct iscsi_sge *)io_task->psgl_handle->pfrag; @@ -2180,35 +2541,28 @@ static void hwi_write_buffer(struct iscsi_wrb *pwrb, struct iscsi_task *task)  		psgl++;  		if (task->data) {  			AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, psgl, -						((u32)(addr & 0xFFFFFFFF))); +				      lower_32_bits(io_task->mtask_addr));  			AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, psgl, -						((u32)(addr >> 32))); +				      upper_32_bits(io_task->mtask_addr));  		}  		AMAP_SET_BITS(struct amap_iscsi_sge, len, psgl, 0x106);  	}  	AMAP_SET_BITS(struct amap_iscsi_sge, last_sge, psgl, 1);  } +/** + * beiscsi_find_mem_req()- Find mem needed + * @phba: ptr to HBA struct + **/  static void beiscsi_find_mem_req(struct beiscsi_hba *phba)  { +	uint8_t mem_descr_index, ulp_num;  	unsigned int num_cq_pages, num_async_pdu_buf_pages;  	unsigned int num_async_pdu_data_pages, wrb_sz_per_cxn;  	unsigned int num_async_pdu_buf_sgl_pages, num_async_pdu_data_sgl_pages;  	num_cq_pages = PAGES_REQUIRED(phba->params.num_cq_entries * \  				      sizeof(struct sol_cqe)); -	num_async_pdu_buf_pages = -			PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ -				       phba->params.defpdu_hdr_sz); -	num_async_pdu_buf_sgl_pages = -			PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ -				       sizeof(struct phys_addr)); -	num_async_pdu_data_pages = -			PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ -				       phba->params.defpdu_data_sz); -	num_async_pdu_data_sgl_pages = -			PAGES_REQUIRED(phba->params.asyncpdus_per_ctrl * \ -				       sizeof(struct phys_addr));  	phba->params.hwi_ws_sz = sizeof(struct hwi_controller); @@ -2230,40 +2584,105 @@ static void beiscsi_find_mem_req(struct beiscsi_hba *phba)  		phba->params.icds_per_ctrl;  	phba->mem_req[HWI_MEM_SGE] = sizeof(struct iscsi_sge) *  		phba->params.num_sge_per_io * phba->params.icds_per_ctrl; - -	phba->mem_req[HWI_MEM_ASYNC_HEADER_BUF] = -		num_async_pdu_buf_pages * PAGE_SIZE; -	phba->mem_req[HWI_MEM_ASYNC_DATA_BUF] = -		num_async_pdu_data_pages * PAGE_SIZE; -	phba->mem_req[HWI_MEM_ASYNC_HEADER_RING] = -		num_async_pdu_buf_sgl_pages * PAGE_SIZE; -	phba->mem_req[HWI_MEM_ASYNC_DATA_RING] = -		num_async_pdu_data_sgl_pages * PAGE_SIZE; -	phba->mem_req[HWI_MEM_ASYNC_HEADER_HANDLE] = -		phba->params.asyncpdus_per_ctrl * -		sizeof(struct async_pdu_handle); -	phba->mem_req[HWI_MEM_ASYNC_DATA_HANDLE] = -		phba->params.asyncpdus_per_ctrl * -		sizeof(struct async_pdu_handle); -	phba->mem_req[HWI_MEM_ASYNC_PDU_CONTEXT] = -		sizeof(struct hwi_async_pdu_context) + -		(phba->params.cxns_per_ctrl * sizeof(struct hwi_async_entry)); +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { + +			num_async_pdu_buf_sgl_pages = +				PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( +					       phba, ulp_num) * +					       sizeof(struct phys_addr)); + +			num_async_pdu_buf_pages = +				PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( +					       phba, ulp_num) * +					       phba->params.defpdu_hdr_sz); + +			num_async_pdu_data_pages = +				PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( +					       phba, ulp_num) * +					       phba->params.defpdu_data_sz); + +			num_async_pdu_data_sgl_pages = +				PAGES_REQUIRED(BEISCSI_GET_CID_COUNT( +					       phba, ulp_num) * +					       sizeof(struct phys_addr)); + +			mem_descr_index = (HWI_MEM_TEMPLATE_HDR_ULP0 + +					  (ulp_num * MEM_DESCR_OFFSET)); +			phba->mem_req[mem_descr_index] = +					BEISCSI_GET_CID_COUNT(phba, ulp_num) * +					BEISCSI_TEMPLATE_HDR_PER_CXN_SIZE; + +			mem_descr_index = (HWI_MEM_ASYNC_HEADER_BUF_ULP0 + +					  (ulp_num * MEM_DESCR_OFFSET)); +			phba->mem_req[mem_descr_index] = +					  num_async_pdu_buf_pages * +					  PAGE_SIZE; + +			mem_descr_index = (HWI_MEM_ASYNC_DATA_BUF_ULP0 + +					  (ulp_num * MEM_DESCR_OFFSET)); +			phba->mem_req[mem_descr_index] = +					  num_async_pdu_data_pages * +					  PAGE_SIZE; + +			mem_descr_index = (HWI_MEM_ASYNC_HEADER_RING_ULP0 + +					  (ulp_num * MEM_DESCR_OFFSET)); +			phba->mem_req[mem_descr_index] = +					  num_async_pdu_buf_sgl_pages * +					  PAGE_SIZE; + +			mem_descr_index = (HWI_MEM_ASYNC_DATA_RING_ULP0 + +					  (ulp_num * MEM_DESCR_OFFSET)); +			phba->mem_req[mem_descr_index] = +					  num_async_pdu_data_sgl_pages * +					  PAGE_SIZE; + +			mem_descr_index = (HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + +					  (ulp_num * MEM_DESCR_OFFSET)); +			phba->mem_req[mem_descr_index] = +					  BEISCSI_GET_CID_COUNT(phba, ulp_num) * +					  sizeof(struct async_pdu_handle); + +			mem_descr_index = (HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + +					  (ulp_num * MEM_DESCR_OFFSET)); +			phba->mem_req[mem_descr_index] = +					  BEISCSI_GET_CID_COUNT(phba, ulp_num) * +					  sizeof(struct async_pdu_handle); + +			mem_descr_index = (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + +					  (ulp_num * MEM_DESCR_OFFSET)); +			phba->mem_req[mem_descr_index] = +					  sizeof(struct hwi_async_pdu_context) + +					 (BEISCSI_GET_CID_COUNT(phba, ulp_num) * +					  sizeof(struct hwi_async_entry)); +		} +	}  }  static int beiscsi_alloc_mem(struct beiscsi_hba *phba)  { -	struct be_mem_descriptor *mem_descr;  	dma_addr_t bus_add; +	struct hwi_controller *phwi_ctrlr; +	struct be_mem_descriptor *mem_descr;  	struct mem_array *mem_arr, *mem_arr_orig;  	unsigned int i, j, alloc_size, curr_alloc_size; -	phba->phwi_ctrlr = kmalloc(phba->params.hwi_ws_sz, GFP_KERNEL); +	phba->phwi_ctrlr = kzalloc(phba->params.hwi_ws_sz, GFP_KERNEL);  	if (!phba->phwi_ctrlr)  		return -ENOMEM; +	/* Allocate memory for wrb_context */ +	phwi_ctrlr = phba->phwi_ctrlr; +	phwi_ctrlr->wrb_context = kzalloc(sizeof(struct hwi_wrb_context) * +					  phba->params.cxns_per_ctrl, +					  GFP_KERNEL); +	if (!phwi_ctrlr->wrb_context) +		return -ENOMEM; +  	phba->init_mem = kcalloc(SE_MEM_MAX, sizeof(*mem_descr),  				 GFP_KERNEL);  	if (!phba->init_mem) { +		kfree(phwi_ctrlr->wrb_context);  		kfree(phba->phwi_ctrlr);  		return -ENOMEM;  	} @@ -2272,12 +2691,19 @@ static int beiscsi_alloc_mem(struct beiscsi_hba *phba)  			       GFP_KERNEL);  	if (!mem_arr_orig) {  		kfree(phba->init_mem); +		kfree(phwi_ctrlr->wrb_context);  		kfree(phba->phwi_ctrlr);  		return -ENOMEM;  	}  	mem_descr = phba->init_mem;  	for (i = 0; i < SE_MEM_MAX; i++) { +		if (!phba->mem_req[i]) { +			mem_descr->mem_array = NULL; +			mem_descr++; +			continue; +		} +  		j = 0;  		mem_arr = mem_arr_orig;  		alloc_size = phba->mem_req[i]; @@ -2342,6 +2768,7 @@ free_mem:  	}  	kfree(mem_arr_orig);  	kfree(phba->init_mem); +	kfree(phba->phwi_ctrlr->wrb_context);  	kfree(phba->phwi_ctrlr);  	return -ENOMEM;  } @@ -2377,40 +2804,66 @@ static void iscsi_init_global_templates(struct beiscsi_hba *phba)  	AMAP_SET_BITS(struct amap_pdu_nop_out, i_bit, pnop_out, 0);  } -static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba) +static int beiscsi_init_wrb_handle(struct beiscsi_hba *phba)  {  	struct be_mem_descriptor *mem_descr_wrbh, *mem_descr_wrb; -	struct wrb_handle *pwrb_handle; +	struct hwi_context_memory *phwi_ctxt; +	struct wrb_handle *pwrb_handle = NULL;  	struct hwi_controller *phwi_ctrlr;  	struct hwi_wrb_context *pwrb_context; -	struct iscsi_wrb *pwrb; -	unsigned int num_cxn_wrbh; -	unsigned int num_cxn_wrb, j, idx, index; +	struct iscsi_wrb *pwrb = NULL; +	unsigned int num_cxn_wrbh = 0; +	unsigned int num_cxn_wrb = 0, j, idx = 0, index;  	mem_descr_wrbh = phba->init_mem;  	mem_descr_wrbh += HWI_MEM_WRBH;  	mem_descr_wrb = phba->init_mem;  	mem_descr_wrb += HWI_MEM_WRB; - -	idx = 0; -	pwrb_handle = mem_descr_wrbh->mem_array[idx].virtual_address; -	num_cxn_wrbh = ((mem_descr_wrbh->mem_array[idx].size) / -			((sizeof(struct wrb_handle)) * -			 phba->params.wrbs_per_cxn));  	phwi_ctrlr = phba->phwi_ctrlr; -	for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { +	/* Allocate memory for WRBQ */ +	phwi_ctxt = phwi_ctrlr->phwi_ctxt; +	phwi_ctxt->be_wrbq = kzalloc(sizeof(struct be_queue_info) * +				     phba->params.cxns_per_ctrl, +				     GFP_KERNEL); +	if (!phwi_ctxt->be_wrbq) { +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : WRBQ Mem Alloc Failed\n"); +		return -ENOMEM; +	} + +	for (index = 0; index < phba->params.cxns_per_ctrl; index++) {  		pwrb_context = &phwi_ctrlr->wrb_context[index];  		pwrb_context->pwrb_handle_base =  				kzalloc(sizeof(struct wrb_handle *) *  					phba->params.wrbs_per_cxn, GFP_KERNEL); +		if (!pwrb_context->pwrb_handle_base) { +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : Mem Alloc Failed. Failing to load\n"); +			goto init_wrb_hndl_failed; +		}  		pwrb_context->pwrb_handle_basestd =  				kzalloc(sizeof(struct wrb_handle *) *  					phba->params.wrbs_per_cxn, GFP_KERNEL); +		if (!pwrb_context->pwrb_handle_basestd) { +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : Mem Alloc Failed. Failing to load\n"); +			goto init_wrb_hndl_failed; +		} +		if (!num_cxn_wrbh) { +			pwrb_handle = +				mem_descr_wrbh->mem_array[idx].virtual_address; +			num_cxn_wrbh = ((mem_descr_wrbh->mem_array[idx].size) / +					((sizeof(struct wrb_handle)) * +					 phba->params.wrbs_per_cxn)); +			idx++; +		} +		pwrb_context->alloc_index = 0; +		pwrb_context->wrb_handles_available = 0; +		pwrb_context->free_index = 0; +  		if (num_cxn_wrbh) { -			pwrb_context->alloc_index = 0; -			pwrb_context->wrb_handles_available = 0;  			for (j = 0; j < phba->params.wrbs_per_cxn; j++) {  				pwrb_context->pwrb_handle_base[j] = pwrb_handle;  				pwrb_context->pwrb_handle_basestd[j] = @@ -2419,49 +2872,21 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)  				pwrb_handle->wrb_index = j;  				pwrb_handle++;  			} -			pwrb_context->free_index = 0; -			num_cxn_wrbh--; -		} else { -			idx++; -			pwrb_handle = -			    mem_descr_wrbh->mem_array[idx].virtual_address; -			num_cxn_wrbh = -			    ((mem_descr_wrbh->mem_array[idx].size) / -			     ((sizeof(struct wrb_handle)) * -			      phba->params.wrbs_per_cxn)); -			pwrb_context->alloc_index = 0; -			for (j = 0; j < phba->params.wrbs_per_cxn; j++) { -				pwrb_context->pwrb_handle_base[j] = pwrb_handle; -				pwrb_context->pwrb_handle_basestd[j] = -				    pwrb_handle; -				pwrb_context->wrb_handles_available++; -				pwrb_handle->wrb_index = j; -				pwrb_handle++; -			} -			pwrb_context->free_index = 0;  			num_cxn_wrbh--;  		}  	}  	idx = 0; -	pwrb = mem_descr_wrb->mem_array[idx].virtual_address; -	num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) / -		      ((sizeof(struct iscsi_wrb) * -			phba->params.wrbs_per_cxn)); -	for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { +	for (index = 0; index < phba->params.cxns_per_ctrl; index++) {  		pwrb_context = &phwi_ctrlr->wrb_context[index]; -		if (num_cxn_wrb) { -			for (j = 0; j < phba->params.wrbs_per_cxn; j++) { -				pwrb_handle = pwrb_context->pwrb_handle_base[j]; -				pwrb_handle->pwrb = pwrb; -				pwrb++; -			} -			num_cxn_wrb--; -		} else { -			idx++; +		if (!num_cxn_wrb) {  			pwrb = mem_descr_wrb->mem_array[idx].virtual_address;  			num_cxn_wrb = (mem_descr_wrb->mem_array[idx].size) / -				      ((sizeof(struct iscsi_wrb) * -					phba->params.wrbs_per_cxn)); +				((sizeof(struct iscsi_wrb) * +				  phba->params.wrbs_per_cxn)); +			idx++; +		} + +		if (num_cxn_wrb) {  			for (j = 0; j < phba->params.wrbs_per_cxn; j++) {  				pwrb_handle = pwrb_context->pwrb_handle_base[j];  				pwrb_handle->pwrb = pwrb; @@ -2470,164 +2895,256 @@ static void beiscsi_init_wrb_handle(struct beiscsi_hba *phba)  			num_cxn_wrb--;  		}  	} +	return 0; +init_wrb_hndl_failed: +	for (j = index; j > 0; j--) { +		pwrb_context = &phwi_ctrlr->wrb_context[j]; +		kfree(pwrb_context->pwrb_handle_base); +		kfree(pwrb_context->pwrb_handle_basestd); +	} +	return -ENOMEM;  } -static void hwi_init_async_pdu_ctx(struct beiscsi_hba *phba) +static int hwi_init_async_pdu_ctx(struct beiscsi_hba *phba)  { +	uint8_t ulp_num;  	struct hwi_controller *phwi_ctrlr;  	struct hba_parameters *p = &phba->params;  	struct hwi_async_pdu_context *pasync_ctx;  	struct async_pdu_handle *pasync_header_h, *pasync_data_h; -	unsigned int index; +	unsigned int index, idx, num_per_mem, num_async_data;  	struct be_mem_descriptor *mem_descr; -	mem_descr = (struct be_mem_descriptor *)phba->init_mem; -	mem_descr += HWI_MEM_ASYNC_PDU_CONTEXT; +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { + +			mem_descr = (struct be_mem_descriptor *)phba->init_mem; +			mem_descr += (HWI_MEM_ASYNC_PDU_CONTEXT_ULP0 + +				     (ulp_num * MEM_DESCR_OFFSET)); + +			phwi_ctrlr = phba->phwi_ctrlr; +			phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num] = +				(struct hwi_async_pdu_context *) +				 mem_descr->mem_array[0].virtual_address; + +			pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; +			memset(pasync_ctx, 0, sizeof(*pasync_ctx)); + +			pasync_ctx->async_entry = +					(struct hwi_async_entry *) +					((long unsigned int)pasync_ctx + +					sizeof(struct hwi_async_pdu_context)); + +			pasync_ctx->num_entries = BEISCSI_GET_CID_COUNT(phba, +						  ulp_num); +			pasync_ctx->buffer_size = p->defpdu_hdr_sz; + +			mem_descr = (struct be_mem_descriptor *)phba->init_mem; +			mem_descr += HWI_MEM_ASYNC_HEADER_BUF_ULP0 + +				(ulp_num * MEM_DESCR_OFFSET); +			if (mem_descr->mem_array[0].virtual_address) { +				beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +					    "BM_%d : hwi_init_async_pdu_ctx" +					    " HWI_MEM_ASYNC_HEADER_BUF_ULP%d va=%p\n", +					    ulp_num, +					    mem_descr->mem_array[0]. +					    virtual_address); +			} else +				beiscsi_log(phba, KERN_WARNING, +					    BEISCSI_LOG_INIT, +					    "BM_%d : No Virtual address for ULP : %d\n", +					    ulp_num); + +			pasync_ctx->async_header.va_base = +				mem_descr->mem_array[0].virtual_address; -	phwi_ctrlr = phba->phwi_ctrlr; -	phwi_ctrlr->phwi_ctxt->pasync_ctx = (struct hwi_async_pdu_context *) +			pasync_ctx->async_header.pa_base.u.a64.address = +				mem_descr->mem_array[0]. +				bus_address.u.a64.address; + +			mem_descr = (struct be_mem_descriptor *)phba->init_mem; +			mem_descr += HWI_MEM_ASYNC_HEADER_RING_ULP0 + +				     (ulp_num * MEM_DESCR_OFFSET); +			if (mem_descr->mem_array[0].virtual_address) { +				beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +					    "BM_%d : hwi_init_async_pdu_ctx" +					    " HWI_MEM_ASYNC_HEADER_RING_ULP%d va=%p\n", +					    ulp_num, +					    mem_descr->mem_array[0]. +					    virtual_address); +			} else +				beiscsi_log(phba, KERN_WARNING, +					    BEISCSI_LOG_INIT, +					    "BM_%d : No Virtual address for ULP : %d\n", +					    ulp_num); + +			pasync_ctx->async_header.ring_base =  				mem_descr->mem_array[0].virtual_address; -	pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx; -	memset(pasync_ctx, 0, sizeof(*pasync_ctx)); - -	pasync_ctx->async_header.num_entries = p->asyncpdus_per_ctrl; -	pasync_ctx->async_header.buffer_size = p->defpdu_hdr_sz; -	pasync_ctx->async_data.buffer_size = p->defpdu_data_sz; -	pasync_ctx->async_data.num_entries = p->asyncpdus_per_ctrl; - -	mem_descr = (struct be_mem_descriptor *)phba->init_mem; -	mem_descr += HWI_MEM_ASYNC_HEADER_BUF; -	if (mem_descr->mem_array[0].virtual_address) { -		SE_DEBUG(DBG_LVL_8, -			 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_BUF" -			 "va=%p\n", mem_descr->mem_array[0].virtual_address); -	} else -		shost_printk(KERN_WARNING, phba->shost, -			     "No Virtual address\n"); -	pasync_ctx->async_header.va_base = -			mem_descr->mem_array[0].virtual_address; +			mem_descr = (struct be_mem_descriptor *)phba->init_mem; +			mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE_ULP0 + +				     (ulp_num * MEM_DESCR_OFFSET); +			if (mem_descr->mem_array[0].virtual_address) { +				beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +					    "BM_%d : hwi_init_async_pdu_ctx" +					    " HWI_MEM_ASYNC_HEADER_HANDLE_ULP%d va=%p\n", +					    ulp_num, +					    mem_descr->mem_array[0]. +					    virtual_address); +			} else +				beiscsi_log(phba, KERN_WARNING, +					    BEISCSI_LOG_INIT, +					    "BM_%d : No Virtual address for ULP : %d\n", +					    ulp_num); + +			pasync_ctx->async_header.handle_base = +				mem_descr->mem_array[0].virtual_address; +			pasync_ctx->async_header.writables = 0; +			INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); + +			mem_descr = (struct be_mem_descriptor *)phba->init_mem; +			mem_descr += HWI_MEM_ASYNC_DATA_RING_ULP0 + +				     (ulp_num * MEM_DESCR_OFFSET); +			if (mem_descr->mem_array[0].virtual_address) { +				beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +					    "BM_%d : hwi_init_async_pdu_ctx" +					    " HWI_MEM_ASYNC_DATA_RING_ULP%d va=%p\n", +					    ulp_num, +					    mem_descr->mem_array[0]. +					    virtual_address); +			} else +				beiscsi_log(phba, KERN_WARNING, +					    BEISCSI_LOG_INIT, +					    "BM_%d : No Virtual address for ULP : %d\n", +					    ulp_num); + +			pasync_ctx->async_data.ring_base = +				mem_descr->mem_array[0].virtual_address; -	pasync_ctx->async_header.pa_base.u.a64.address = -			mem_descr->mem_array[0].bus_address.u.a64.address; +			mem_descr = (struct be_mem_descriptor *)phba->init_mem; +			mem_descr += HWI_MEM_ASYNC_DATA_HANDLE_ULP0 + +				     (ulp_num * MEM_DESCR_OFFSET); +			if (!mem_descr->mem_array[0].virtual_address) +				beiscsi_log(phba, KERN_WARNING, +					    BEISCSI_LOG_INIT, +					    "BM_%d : No Virtual address for ULP : %d\n", +					    ulp_num); -	mem_descr = (struct be_mem_descriptor *)phba->init_mem; -	mem_descr += HWI_MEM_ASYNC_HEADER_RING; -	if (mem_descr->mem_array[0].virtual_address) { -		SE_DEBUG(DBG_LVL_8, -			 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_RING" -			 "va=%p\n", mem_descr->mem_array[0].virtual_address); -	} else -		shost_printk(KERN_WARNING, phba->shost, -			    "No Virtual address\n"); -	pasync_ctx->async_header.ring_base = -			mem_descr->mem_array[0].virtual_address; - -	mem_descr = (struct be_mem_descriptor *)phba->init_mem; -	mem_descr += HWI_MEM_ASYNC_HEADER_HANDLE; -	if (mem_descr->mem_array[0].virtual_address) { -		SE_DEBUG(DBG_LVL_8, -			 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_HEADER_HANDLE" -			 "va=%p\n", mem_descr->mem_array[0].virtual_address); -	} else -		shost_printk(KERN_WARNING, phba->shost, -			    "No Virtual address\n"); - -	pasync_ctx->async_header.handle_base = -			mem_descr->mem_array[0].virtual_address; -	pasync_ctx->async_header.writables = 0; -	INIT_LIST_HEAD(&pasync_ctx->async_header.free_list); - -	mem_descr = (struct be_mem_descriptor *)phba->init_mem; -	mem_descr += HWI_MEM_ASYNC_DATA_BUF; -	if (mem_descr->mem_array[0].virtual_address) { -		SE_DEBUG(DBG_LVL_8, -			 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_BUF" -			 "va=%p\n", mem_descr->mem_array[0].virtual_address); -	} else -		shost_printk(KERN_WARNING, phba->shost, -			    "No Virtual address\n"); -	pasync_ctx->async_data.va_base = -			mem_descr->mem_array[0].virtual_address; -	pasync_ctx->async_data.pa_base.u.a64.address = -			mem_descr->mem_array[0].bus_address.u.a64.address; - -	mem_descr = (struct be_mem_descriptor *)phba->init_mem; -	mem_descr += HWI_MEM_ASYNC_DATA_RING; -	if (mem_descr->mem_array[0].virtual_address) { -		SE_DEBUG(DBG_LVL_8, -			 "hwi_init_async_pdu_ctx HWI_MEM_ASYNC_DATA_RING" -			 "va=%p\n", mem_descr->mem_array[0].virtual_address); -	} else -		shost_printk(KERN_WARNING, phba->shost, -			     "No Virtual address\n"); - -	pasync_ctx->async_data.ring_base = -			mem_descr->mem_array[0].virtual_address; - -	mem_descr = (struct be_mem_descriptor *)phba->init_mem; -	mem_descr += HWI_MEM_ASYNC_DATA_HANDLE; -	if (!mem_descr->mem_array[0].virtual_address) -		shost_printk(KERN_WARNING, phba->shost, -			    "No Virtual address\n"); - -	pasync_ctx->async_data.handle_base = -			mem_descr->mem_array[0].virtual_address; -	pasync_ctx->async_data.writables = 0; -	INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); - -	pasync_header_h = -		(struct async_pdu_handle *)pasync_ctx->async_header.handle_base; -	pasync_data_h = -		(struct async_pdu_handle *)pasync_ctx->async_data.handle_base; - -	for (index = 0; index < p->asyncpdus_per_ctrl; index++) { -		pasync_header_h->cri = -1; -		pasync_header_h->index = (char)index; -		INIT_LIST_HEAD(&pasync_header_h->link); -		pasync_header_h->pbuffer = -			(void *)((unsigned long) -			(pasync_ctx->async_header.va_base) + -			(p->defpdu_hdr_sz * index)); - -		pasync_header_h->pa.u.a64.address = -			pasync_ctx->async_header.pa_base.u.a64.address + -			(p->defpdu_hdr_sz * index); - -		list_add_tail(&pasync_header_h->link, -				&pasync_ctx->async_header.free_list); -		pasync_header_h++; -		pasync_ctx->async_header.free_entries++; -		pasync_ctx->async_header.writables++; - -		INIT_LIST_HEAD(&pasync_ctx->async_entry[index].wait_queue.list); -		INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. -			       header_busy_list); -		pasync_data_h->cri = -1; -		pasync_data_h->index = (char)index; -		INIT_LIST_HEAD(&pasync_data_h->link); -		pasync_data_h->pbuffer = -			(void *)((unsigned long) -			(pasync_ctx->async_data.va_base) + -			(p->defpdu_data_sz * index)); - -		pasync_data_h->pa.u.a64.address = -		    pasync_ctx->async_data.pa_base.u.a64.address + -		    (p->defpdu_data_sz * index); - -		list_add_tail(&pasync_data_h->link, -			      &pasync_ctx->async_data.free_list); -		pasync_data_h++; -		pasync_ctx->async_data.free_entries++; -		pasync_ctx->async_data.writables++; - -		INIT_LIST_HEAD(&pasync_ctx->async_entry[index].data_busy_list); -	} - -	pasync_ctx->async_header.host_write_ptr = 0; -	pasync_ctx->async_header.ep_read_ptr = -1; -	pasync_ctx->async_data.host_write_ptr = 0; -	pasync_ctx->async_data.ep_read_ptr = -1; +			pasync_ctx->async_data.handle_base = +				mem_descr->mem_array[0].virtual_address; +			pasync_ctx->async_data.writables = 0; +			INIT_LIST_HEAD(&pasync_ctx->async_data.free_list); + +			pasync_header_h = +				(struct async_pdu_handle *) +				pasync_ctx->async_header.handle_base; +			pasync_data_h = +				(struct async_pdu_handle *) +				pasync_ctx->async_data.handle_base; + +			mem_descr = (struct be_mem_descriptor *)phba->init_mem; +			mem_descr += HWI_MEM_ASYNC_DATA_BUF_ULP0 + +				     (ulp_num * MEM_DESCR_OFFSET); +			if (mem_descr->mem_array[0].virtual_address) { +				beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +					    "BM_%d : hwi_init_async_pdu_ctx" +					    " HWI_MEM_ASYNC_DATA_BUF_ULP%d va=%p\n", +					    ulp_num, +					    mem_descr->mem_array[0]. +					    virtual_address); +			} else +				beiscsi_log(phba, KERN_WARNING, +					    BEISCSI_LOG_INIT, +					    "BM_%d : No Virtual address for ULP : %d\n", +					    ulp_num); + +			idx = 0; +			pasync_ctx->async_data.va_base = +				mem_descr->mem_array[idx].virtual_address; +			pasync_ctx->async_data.pa_base.u.a64.address = +				mem_descr->mem_array[idx]. +				bus_address.u.a64.address; + +			num_async_data = ((mem_descr->mem_array[idx].size) / +					phba->params.defpdu_data_sz); +			num_per_mem = 0; + +			for (index = 0;	index < BEISCSI_GET_CID_COUNT +					(phba, ulp_num); index++) { +				pasync_header_h->cri = -1; +				pasync_header_h->index = (char)index; +				INIT_LIST_HEAD(&pasync_header_h->link); +				pasync_header_h->pbuffer = +					(void *)((unsigned long) +						 (pasync_ctx-> +						  async_header.va_base) + +						 (p->defpdu_hdr_sz * index)); + +				pasync_header_h->pa.u.a64.address = +					pasync_ctx->async_header.pa_base.u.a64. +					address + (p->defpdu_hdr_sz * index); + +				list_add_tail(&pasync_header_h->link, +					      &pasync_ctx->async_header. +					      free_list); +				pasync_header_h++; +				pasync_ctx->async_header.free_entries++; +				pasync_ctx->async_header.writables++; + +				INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. +					       wait_queue.list); +				INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. +					       header_busy_list); +				pasync_data_h->cri = -1; +				pasync_data_h->index = (char)index; +				INIT_LIST_HEAD(&pasync_data_h->link); + +				if (!num_async_data) { +					num_per_mem = 0; +					idx++; +					pasync_ctx->async_data.va_base = +						mem_descr->mem_array[idx]. +						virtual_address; +					pasync_ctx->async_data.pa_base.u. +						a64.address = +						mem_descr->mem_array[idx]. +						bus_address.u.a64.address; +					num_async_data = +						((mem_descr->mem_array[idx]. +						  size) / +						 phba->params.defpdu_data_sz); +				} +				pasync_data_h->pbuffer = +					(void *)((unsigned long) +					(pasync_ctx->async_data.va_base) + +					(p->defpdu_data_sz * num_per_mem)); + +				pasync_data_h->pa.u.a64.address = +					pasync_ctx->async_data.pa_base.u.a64. +					address + (p->defpdu_data_sz * +					num_per_mem); +				num_per_mem++; +				num_async_data--; + +				list_add_tail(&pasync_data_h->link, +					      &pasync_ctx->async_data. +					      free_list); +				pasync_data_h++; +				pasync_ctx->async_data.free_entries++; +				pasync_ctx->async_data.writables++; + +				INIT_LIST_HEAD(&pasync_ctx->async_entry[index]. +					       data_busy_list); +			} + +			pasync_ctx->async_header.host_write_ptr = 0; +			pasync_ctx->async_header.ep_read_ptr = -1; +			pasync_ctx->async_data.host_write_ptr = 0; +			pasync_ctx->async_data.ep_read_ptr = -1; +		} +	} + +	return 0;  }  static int @@ -2696,7 +3213,7 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,  			     struct hwi_context_memory *phwi_context)  {  	unsigned int i, num_eq_pages; -	int ret, eq_for_mcc; +	int ret = 0, eq_for_mcc;  	struct be_queue_info *eq;  	struct be_dma_mem *mem;  	void *eq_vaddress; @@ -2723,8 +3240,8 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,  		ret = be_fill_queue(eq, phba->params.num_eq_entries,  				    sizeof(struct be_eq_entry), eq_vaddress);  		if (ret) { -			shost_printk(KERN_ERR, phba->shost, -				     "be_fill_queue Failed for EQ\n"); +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : be_fill_queue Failed for EQ\n");  			goto create_eq_error;  		} @@ -2732,16 +3249,19 @@ static int beiscsi_create_eqs(struct beiscsi_hba *phba,  		ret = beiscsi_cmd_eq_create(&phba->ctrl, eq,  					    phwi_context->cur_eqd);  		if (ret) { -			shost_printk(KERN_ERR, phba->shost, -				     "beiscsi_cmd_eq_create" -				     "Failedfor EQ\n"); +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : beiscsi_cmd_eq_create" +				    "Failed for EQ\n");  			goto create_eq_error;  		} -		SE_DEBUG(DBG_LVL_8, "eqid = %d\n", phwi_context->be_eq[i].q.id); + +		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +			    "BM_%d : eqid = %d\n", +			    phwi_context->be_eq[i].q.id);  	}  	return 0;  create_eq_error: -	for (i = 0; i < (phba->num_cpus + 1); i++) { +	for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) {  		eq = &phwi_context->be_eq[i].q;  		mem = &eq->dma_mem;  		if (mem->va) @@ -2756,7 +3276,7 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba,  			     struct hwi_context_memory *phwi_context)  {  	unsigned int i, num_cq_pages; -	int ret; +	int ret = 0;  	struct be_queue_info *cq, *eq;  	struct be_dma_mem *mem;  	struct be_eq_obj *pbe_eq; @@ -2781,8 +3301,9 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba,  		ret = be_fill_queue(cq, phba->params.num_cq_entries,  				    sizeof(struct sol_cqe), cq_vaddress);  		if (ret) { -			shost_printk(KERN_ERR, phba->shost, -				     "be_fill_queue Failed for ISCSI CQ\n"); +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : be_fill_queue Failed " +				    "for ISCSI CQ\n");  			goto create_cq_error;  		} @@ -2790,14 +3311,14 @@ static int beiscsi_create_cqs(struct beiscsi_hba *phba,  		ret = beiscsi_cmd_cq_create(&phba->ctrl, cq, eq, false,  					    false, 0);  		if (ret) { -			shost_printk(KERN_ERR, phba->shost, -				     "beiscsi_cmd_eq_create" -				     "Failed for ISCSI CQ\n"); +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : beiscsi_cmd_eq_create" +				    "Failed for ISCSI CQ\n");  			goto create_cq_error;  		} -		SE_DEBUG(DBG_LVL_8, "iscsi cq_id is %d for eq_id %d\n", -						 cq->id, eq->id); -		SE_DEBUG(DBG_LVL_8, "ISCSI CQ CREATED\n"); +		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +			    "BM_%d : iscsi cq_id is %d for eq_id %d\n" +			    "iSCSI CQ CREATED\n", cq->id, eq->id);  	}  	return 0; @@ -2818,7 +3339,7 @@ static int  beiscsi_create_def_hdr(struct beiscsi_hba *phba,  		       struct hwi_context_memory *phwi_context,  		       struct hwi_controller *phwi_ctrlr, -		       unsigned int def_pdu_ring_sz) +		       unsigned int def_pdu_ring_sz, uint8_t ulp_num)  {  	unsigned int idx;  	int ret; @@ -2828,34 +3349,42 @@ beiscsi_create_def_hdr(struct beiscsi_hba *phba,  	void *dq_vaddress;  	idx = 0; -	dq = &phwi_context->be_def_hdrq; +	dq = &phwi_context->be_def_hdrq[ulp_num];  	cq = &phwi_context->be_cq[0];  	mem = &dq->dma_mem;  	mem_descr = phba->init_mem; -	mem_descr += HWI_MEM_ASYNC_HEADER_RING; +	mem_descr += HWI_MEM_ASYNC_HEADER_RING_ULP0 + +		    (ulp_num * MEM_DESCR_OFFSET);  	dq_vaddress = mem_descr->mem_array[idx].virtual_address;  	ret = be_fill_queue(dq, mem_descr->mem_array[0].size /  			    sizeof(struct phys_addr),  			    sizeof(struct phys_addr), dq_vaddress);  	if (ret) { -		shost_printk(KERN_ERR, phba->shost, -			     "be_fill_queue Failed for DEF PDU HDR\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : be_fill_queue Failed for DEF PDU HDR on ULP : %d\n", +			    ulp_num); +  		return ret;  	}  	mem->dma = (unsigned long)mem_descr->mem_array[idx].  				  bus_address.u.a64.address;  	ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dq,  					      def_pdu_ring_sz, -					      phba->params.defpdu_hdr_sz); +					      phba->params.defpdu_hdr_sz, +					      BEISCSI_DEFQ_HDR, ulp_num);  	if (ret) { -		shost_printk(KERN_ERR, phba->shost, -			     "be_cmd_create_default_pdu_queue Failed DEFHDR\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : be_cmd_create_default_pdu_queue Failed DEFHDR on ULP : %d\n", +			    ulp_num); +  		return ret;  	} -	phwi_ctrlr->default_pdu_hdr.id = phwi_context->be_def_hdrq.id; -	SE_DEBUG(DBG_LVL_8, "iscsi def pdu id is %d\n", -		 phwi_context->be_def_hdrq.id); -	hwi_post_async_buffers(phba, 1); + +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "BM_%d : iscsi hdr def pdu id for ULP : %d is %d\n", +		    ulp_num, +		    phwi_context->be_def_hdrq[ulp_num].id); +	hwi_post_async_buffers(phba, BEISCSI_DEFQ_HDR, ulp_num);  	return 0;  } @@ -2863,7 +3392,7 @@ static int  beiscsi_create_def_data(struct beiscsi_hba *phba,  			struct hwi_context_memory *phwi_context,  			struct hwi_controller *phwi_ctrlr, -			unsigned int def_pdu_ring_sz) +			unsigned int def_pdu_ring_sz, uint8_t ulp_num)  {  	unsigned int idx;  	int ret; @@ -2873,36 +3402,83 @@ beiscsi_create_def_data(struct beiscsi_hba *phba,  	void *dq_vaddress;  	idx = 0; -	dataq = &phwi_context->be_def_dataq; +	dataq = &phwi_context->be_def_dataq[ulp_num];  	cq = &phwi_context->be_cq[0];  	mem = &dataq->dma_mem;  	mem_descr = phba->init_mem; -	mem_descr += HWI_MEM_ASYNC_DATA_RING; +	mem_descr += HWI_MEM_ASYNC_DATA_RING_ULP0 + +		    (ulp_num * MEM_DESCR_OFFSET);  	dq_vaddress = mem_descr->mem_array[idx].virtual_address;  	ret = be_fill_queue(dataq, mem_descr->mem_array[0].size /  			    sizeof(struct phys_addr),  			    sizeof(struct phys_addr), dq_vaddress);  	if (ret) { -		shost_printk(KERN_ERR, phba->shost, -			     "be_fill_queue Failed for DEF PDU DATA\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : be_fill_queue Failed for DEF PDU " +			    "DATA on ULP : %d\n", +			    ulp_num); +  		return ret;  	}  	mem->dma = (unsigned long)mem_descr->mem_array[idx].  				  bus_address.u.a64.address;  	ret = be_cmd_create_default_pdu_queue(&phba->ctrl, cq, dataq,  					      def_pdu_ring_sz, -					      phba->params.defpdu_data_sz); +					      phba->params.defpdu_data_sz, +					      BEISCSI_DEFQ_DATA, ulp_num);  	if (ret) { -		shost_printk(KERN_ERR, phba->shost, -			     "be_cmd_create_default_pdu_queue Failed" -			     " for DEF PDU DATA\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d be_cmd_create_default_pdu_queue" +			    " Failed for DEF PDU DATA on ULP : %d\n", +			    ulp_num);  		return ret;  	} -	phwi_ctrlr->default_pdu_data.id = phwi_context->be_def_dataq.id; -	SE_DEBUG(DBG_LVL_8, "iscsi def data id is %d\n", -		 phwi_context->be_def_dataq.id); -	hwi_post_async_buffers(phba, 0); -	SE_DEBUG(DBG_LVL_8, "DEFAULT PDU DATA RING CREATED\n"); + +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "BM_%d : iscsi def data id on ULP : %d is  %d\n", +		    ulp_num, +		    phwi_context->be_def_dataq[ulp_num].id); + +	hwi_post_async_buffers(phba, BEISCSI_DEFQ_DATA, ulp_num); +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "BM_%d : DEFAULT PDU DATA RING CREATED" +		    "on ULP : %d\n", ulp_num); + +	return 0; +} + + +static int +beiscsi_post_template_hdr(struct beiscsi_hba *phba) +{ +	struct be_mem_descriptor *mem_descr; +	struct mem_array *pm_arr; +	struct be_dma_mem sgl; +	int status, ulp_num; + +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { +			mem_descr = (struct be_mem_descriptor *)phba->init_mem; +			mem_descr += HWI_MEM_TEMPLATE_HDR_ULP0 + +				    (ulp_num * MEM_DESCR_OFFSET); +			pm_arr = mem_descr->mem_array; + +			hwi_build_be_sgl_arr(phba, pm_arr, &sgl); +			status = be_cmd_iscsi_post_template_hdr( +				 &phba->ctrl, &sgl); + +			if (status != 0) { +				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +					    "BM_%d : Post Template HDR Failed for" +					    "ULP_%d\n", ulp_num); +				return status; +			} + +			beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +				    "BM_%d : Template HDR Pages Posted for" +				    "ULP_%d\n", ulp_num); +		} +	}  	return 0;  } @@ -2913,14 +3489,18 @@ beiscsi_post_pages(struct beiscsi_hba *phba)  	struct mem_array *pm_arr;  	unsigned int page_offset, i;  	struct be_dma_mem sgl; -	int status; +	int status, ulp_num = 0;  	mem_descr = phba->init_mem;  	mem_descr += HWI_MEM_SGE;  	pm_arr = mem_descr->mem_array; +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) +			break; +  	page_offset = (sizeof(struct iscsi_sge) * phba->params.num_sge_per_io * -			phba->fw_config.iscsi_icd_start) / PAGE_SIZE; +			phba->fw_config.iscsi_icd_start[ulp_num]) / PAGE_SIZE;  	for (i = 0; i < mem_descr->num_elements; i++) {  		hwi_build_be_sgl_arr(phba, pm_arr, &sgl);  		status = be_cmd_iscsi_post_sgl_pages(&phba->ctrl, &sgl, @@ -2928,22 +3508,25 @@ beiscsi_post_pages(struct beiscsi_hba *phba)  						(pm_arr->size / PAGE_SIZE));  		page_offset += pm_arr->size / PAGE_SIZE;  		if (status != 0) { -			shost_printk(KERN_ERR, phba->shost, -				     "post sgl failed.\n"); +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : post sgl failed.\n");  			return status;  		}  		pm_arr++;  	} -	SE_DEBUG(DBG_LVL_8, "POSTED PAGES\n"); +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "BM_%d : POSTED PAGES\n");  	return 0;  }  static void be_queue_free(struct beiscsi_hba *phba, struct be_queue_info *q)  {  	struct be_dma_mem *mem = &q->dma_mem; -	if (mem->va) +	if (mem->va) {  		pci_free_consistent(phba->pcidev, mem->size,  			mem->va, mem->dma); +		mem->va = NULL; +	}  }  static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q, @@ -2969,12 +3552,15 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,  {  	unsigned int wrb_mem_index, offset, size, num_wrb_rings;  	u64 pa_addr_lo; -	unsigned int idx, num, i; +	unsigned int idx, num, i, ulp_num;  	struct mem_array *pwrb_arr;  	void *wrb_vaddr;  	struct be_dma_mem sgl;  	struct be_mem_descriptor *mem_descr; +	struct hwi_wrb_context *pwrb_context;  	int status; +	uint8_t ulp_count = 0, ulp_base_num = 0; +	uint16_t cid_count_ulp[BEISCSI_ULP_COUNT] = { 0 };  	idx = 0;  	mem_descr = phba->init_mem; @@ -2982,8 +3568,8 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,  	pwrb_arr = kmalloc(sizeof(*pwrb_arr) * phba->params.cxns_per_ctrl,  			   GFP_KERNEL);  	if (!pwrb_arr) { -		shost_printk(KERN_ERR, phba->shost, -			     "Memory alloc failed in create wrb ring.\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Memory alloc failed in create wrb ring.\n");  		return -ENOMEM;  	}  	wrb_vaddr = mem_descr->mem_array[idx].virtual_address; @@ -3018,22 +3604,45 @@ beiscsi_create_wrb_rings(struct beiscsi_hba *phba,  			num_wrb_rings--;  		}  	} + +	/* Get the ULP Count */ +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { +			ulp_count++; +			ulp_base_num = ulp_num; +			cid_count_ulp[ulp_num] = +				BEISCSI_GET_CID_COUNT(phba, ulp_num); +		} +  	for (i = 0; i < phba->params.cxns_per_ctrl; i++) {  		wrb_mem_index = 0;  		offset = 0;  		size = 0; +		if (ulp_count > 1) { +			ulp_base_num = (ulp_base_num + 1) % BEISCSI_ULP_COUNT; + +			if (!cid_count_ulp[ulp_base_num]) +				ulp_base_num = (ulp_base_num + 1) % +						BEISCSI_ULP_COUNT; + +			cid_count_ulp[ulp_base_num]--; +		} + +  		hwi_build_be_sgl_by_offset(phba, &pwrb_arr[i], &sgl);  		status = be_cmd_wrbq_create(&phba->ctrl, &sgl, -					    &phwi_context->be_wrbq[i]); +					    &phwi_context->be_wrbq[i], +					    &phwi_ctrlr->wrb_context[i], +					    ulp_base_num);  		if (status != 0) { -			shost_printk(KERN_ERR, phba->shost, -				     "wrbq create failed."); +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : wrbq create failed.");  			kfree(pwrb_arr);  			return status;  		} -		phwi_ctrlr->wrb_context[i * 2].cid = phwi_context->be_wrbq[i]. -								   id; +		pwrb_context = &phwi_ctrlr->wrb_context[i]; +		BE_SET_CID_TO_CRI(i, pwrb_context->cid);  	}  	kfree(pwrb_arr);  	return 0; @@ -3046,7 +3655,7 @@ static void free_wrb_handles(struct beiscsi_hba *phba)  	struct hwi_wrb_context *pwrb_context;  	phwi_ctrlr = phba->phwi_ctrlr; -	for (index = 0; index < phba->params.cxns_per_ctrl * 2; index += 2) { +	for (index = 0; index < phba->params.cxns_per_ctrl; index++) {  		pwrb_context = &phwi_ctrlr->wrb_context[index];  		kfree(pwrb_context->pwrb_handle_base);  		kfree(pwrb_context->pwrb_handle_basestd); @@ -3075,24 +3684,36 @@ static void hwi_cleanup(struct beiscsi_hba *phba)  	struct be_ctrl_info *ctrl = &phba->ctrl;  	struct hwi_controller *phwi_ctrlr;  	struct hwi_context_memory *phwi_context; -	int i, eq_num; +	struct hwi_async_pdu_context *pasync_ctx; +	int i, eq_for_mcc, ulp_num;  	phwi_ctrlr = phba->phwi_ctrlr;  	phwi_context = phwi_ctrlr->phwi_ctxt; + +	be_cmd_iscsi_remove_template_hdr(ctrl); +  	for (i = 0; i < phba->params.cxns_per_ctrl; i++) {  		q = &phwi_context->be_wrbq[i];  		if (q->created)  			beiscsi_cmd_q_destroy(ctrl, q, QTYPE_WRBQ);  	} +	kfree(phwi_context->be_wrbq);  	free_wrb_handles(phba); -	q = &phwi_context->be_def_hdrq; -	if (q->created) -		beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { -	q = &phwi_context->be_def_dataq; -	if (q->created) -		beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); +			q = &phwi_context->be_def_hdrq[ulp_num]; +			if (q->created) +				beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); + +			q = &phwi_context->be_def_dataq[ulp_num]; +			if (q->created) +				beiscsi_cmd_q_destroy(ctrl, q, QTYPE_DPDUQ); + +			pasync_ctx = phwi_ctrlr->phwi_ctxt->pasync_ctx[ulp_num]; +		} +	}  	beiscsi_cmd_q_destroy(ctrl, NULL, QTYPE_SGL); @@ -3101,16 +3722,18 @@ static void hwi_cleanup(struct beiscsi_hba *phba)  		if (q->created)  			beiscsi_cmd_q_destroy(ctrl, q, QTYPE_CQ);  	} + +	be_mcc_queues_destroy(phba);  	if (phba->msix_enabled) -		eq_num = 1; +		eq_for_mcc = 1;  	else -		eq_num = 0; -	for (i = 0; i < (phba->num_cpus + eq_num); i++) { +		eq_for_mcc = 0; +	for (i = 0; i < (phba->num_cpus + eq_for_mcc); i++) {  		q = &phwi_context->be_eq[i].q;  		if (q->created)  			beiscsi_cmd_q_destroy(ctrl, q, QTYPE_EQ);  	} -	be_mcc_queues_destroy(phba); +	be_cmd_fw_uninit(ctrl);  }  static int be_mcc_queues_create(struct beiscsi_hba *phba, @@ -3156,16 +3779,42 @@ err:  	return -ENOMEM;  } -static int find_num_cpus(void) +/** + * find_num_cpus()- Get the CPU online count + * @phba: ptr to priv structure + * + * CPU count is used for creating EQ. + **/ +static void find_num_cpus(struct beiscsi_hba *phba)  {  	int  num_cpus = 0;  	num_cpus = num_online_cpus(); -	if (num_cpus >= MAX_CPUS) -		num_cpus = MAX_CPUS - 1; -	SE_DEBUG(DBG_LVL_8, "num_cpus = %d\n", num_cpus); -	return num_cpus; +	switch (phba->generation) { +	case BE_GEN2: +	case BE_GEN3: +		phba->num_cpus = (num_cpus > BEISCSI_MAX_NUM_CPUS) ? +				  BEISCSI_MAX_NUM_CPUS : num_cpus; +		break; +	case BE_GEN4: +		/* +		 * If eqid_count == 1 fall back to +		 * INTX mechanism +		 **/ +		if (phba->fw_config.eqid_count == 1) { +			enable_msix = 0; +			phba->num_cpus = 1; +			return; +		} + +		phba->num_cpus = +			(num_cpus > (phba->fw_config.eqid_count - 1)) ? +			(phba->fw_config.eqid_count - 1) : num_cpus; +		break; +	default: +		phba->num_cpus = 1; +	}  }  static int hwi_init_port(struct beiscsi_hba *phba) @@ -3174,20 +3823,19 @@ static int hwi_init_port(struct beiscsi_hba *phba)  	struct hwi_context_memory *phwi_context;  	unsigned int def_pdu_ring_sz;  	struct be_ctrl_info *ctrl = &phba->ctrl; -	int status; +	int status, ulp_num; -	def_pdu_ring_sz = -		phba->params.asyncpdus_per_ctrl * sizeof(struct phys_addr);  	phwi_ctrlr = phba->phwi_ctrlr;  	phwi_context = phwi_ctrlr->phwi_ctxt; -	phwi_context->max_eqd = 0; +	phwi_context->max_eqd = 128;  	phwi_context->min_eqd = 0; -	phwi_context->cur_eqd = 64; +	phwi_context->cur_eqd = 0;  	be_cmd_fw_initialize(&phba->ctrl);  	status = beiscsi_create_eqs(phba, phwi_context);  	if (status != 0) { -		shost_printk(KERN_ERR, phba->shost, "EQ not created\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : EQ not created\n");  		goto error;  	} @@ -3197,53 +3845,98 @@ static int hwi_init_port(struct beiscsi_hba *phba)  	status = mgmt_check_supported_fw(ctrl, phba);  	if (status != 0) { -		shost_printk(KERN_ERR, phba->shost, -			     "Unsupported fw version\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Unsupported fw version\n");  		goto error;  	}  	status = beiscsi_create_cqs(phba, phwi_context);  	if (status != 0) { -		shost_printk(KERN_ERR, phba->shost, "CQ not created\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : CQ not created\n");  		goto error;  	} -	status = beiscsi_create_def_hdr(phba, phwi_context, phwi_ctrlr, -					def_pdu_ring_sz); -	if (status != 0) { -		shost_printk(KERN_ERR, phba->shost, -			     "Default Header not created\n"); -		goto error; +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { + +			def_pdu_ring_sz = +				BEISCSI_GET_CID_COUNT(phba, ulp_num) * +				sizeof(struct phys_addr); + +			status = beiscsi_create_def_hdr(phba, phwi_context, +							phwi_ctrlr, +							def_pdu_ring_sz, +							ulp_num); +			if (status != 0) { +				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +					    "BM_%d : Default Header not created for ULP : %d\n", +					    ulp_num); +				goto error; +			} + +			status = beiscsi_create_def_data(phba, phwi_context, +							 phwi_ctrlr, +							 def_pdu_ring_sz, +							 ulp_num); +			if (status != 0) { +				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +					    "BM_%d : Default Data not created for ULP : %d\n", +					    ulp_num); +				goto error; +			} +		}  	} -	status = beiscsi_create_def_data(phba, phwi_context, -					 phwi_ctrlr, def_pdu_ring_sz); +	status = beiscsi_post_pages(phba);  	if (status != 0) { -		shost_printk(KERN_ERR, phba->shost, -			     "Default Data not created\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Post SGL Pages Failed\n");  		goto error;  	} -	status = beiscsi_post_pages(phba); +	status = beiscsi_post_template_hdr(phba);  	if (status != 0) { -		shost_printk(KERN_ERR, phba->shost, "Post SGL Pages Failed\n"); -		goto error; +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Template HDR Posting for CXN Failed\n");  	}  	status = beiscsi_create_wrb_rings(phba,	phwi_context, phwi_ctrlr);  	if (status != 0) { -		shost_printk(KERN_ERR, phba->shost, -			     "WRB Rings not created\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : WRB Rings not created\n");  		goto error;  	} -	SE_DEBUG(DBG_LVL_8, "hwi_init_port success\n"); +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		uint16_t async_arr_idx = 0; + +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) { +			uint16_t cri = 0; +			struct hwi_async_pdu_context *pasync_ctx; + +			pasync_ctx = HWI_GET_ASYNC_PDU_CTX( +				     phwi_ctrlr, ulp_num); +			for (cri = 0; cri < +			     phba->params.cxns_per_ctrl; cri++) { +				if (ulp_num == BEISCSI_GET_ULP_FROM_CRI +					       (phwi_ctrlr, cri)) +					pasync_ctx->cid_to_async_cri_map[ +					phwi_ctrlr->wrb_context[cri].cid] = +					async_arr_idx++; +			} +		} +	} + +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "BM_%d : hwi_init_port success\n");  	return 0;  error: -	shost_printk(KERN_ERR, phba->shost, "hwi_init_port failed"); +	beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +		    "BM_%d : hwi_init_port failed");  	hwi_cleanup(phba); -	return -ENOMEM; +	return status;  }  static int hwi_init_controller(struct beiscsi_hba *phba) @@ -3254,21 +3947,30 @@ static int hwi_init_controller(struct beiscsi_hba *phba)  	if (1 == phba->init_mem[HWI_MEM_ADDN_CONTEXT].num_elements) {  		phwi_ctrlr->phwi_ctxt = (struct hwi_context_memory *)phba->  		    init_mem[HWI_MEM_ADDN_CONTEXT].mem_array[0].virtual_address; -		SE_DEBUG(DBG_LVL_8, " phwi_ctrlr->phwi_ctxt=%p\n", -			 phwi_ctrlr->phwi_ctxt); +		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +			    "BM_%d :  phwi_ctrlr->phwi_ctxt=%p\n", +			    phwi_ctrlr->phwi_ctxt);  	} else { -		shost_printk(KERN_ERR, phba->shost, -			     "HWI_MEM_ADDN_CONTEXT is more than one element." -			     "Failing to load\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : HWI_MEM_ADDN_CONTEXT is more " +			    "than one element.Failing to load\n");  		return -ENOMEM;  	}  	iscsi_init_global_templates(phba); -	beiscsi_init_wrb_handle(phba); -	hwi_init_async_pdu_ctx(phba); +	if (beiscsi_init_wrb_handle(phba)) +		return -ENOMEM; + +	if (hwi_init_async_pdu_ctx(phba)) { +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : hwi_init_async_pdu_ctx failed\n"); +		return -ENOMEM; +	} +  	if (hwi_init_port(phba) != 0) { -		shost_printk(KERN_ERR, phba->shost, -			     "hwi_init_controller failed\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : hwi_init_controller failed\n"); +  		return -ENOMEM;  	}  	return 0; @@ -3290,10 +3992,12 @@ static void beiscsi_free_mem(struct beiscsi_hba *phba)  			  (unsigned long)mem_descr->mem_array[j - 1].  			  bus_address.u.a64.address);  		} +  		kfree(mem_descr->mem_array);  		mem_descr++;  	}  	kfree(phba->init_mem); +	kfree(phba->phwi_ctrlr->wrb_context);  	kfree(phba->phwi_ctrlr);  } @@ -3303,20 +4007,23 @@ static int beiscsi_init_controller(struct beiscsi_hba *phba)  	ret = beiscsi_get_memory(phba);  	if (ret < 0) { -		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe -" -			     "Failed in beiscsi_alloc_memory\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : beiscsi_dev_probe -" +			    "Failed in beiscsi_alloc_memory\n");  		return ret;  	}  	ret = hwi_init_controller(phba);  	if (ret)  		goto free_init; -	SE_DEBUG(DBG_LVL_8, "Return success from beiscsi_init_controller"); +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "BM_%d : Return success from beiscsi_init_controller"); +  	return 0;  free_init:  	beiscsi_free_mem(phba); -	return -ENOMEM; +	return ret;  }  static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba) @@ -3325,6 +4032,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)  	struct sgl_handle *psgl_handle;  	struct iscsi_sge *pfrag;  	unsigned int arr_index, i, idx; +	unsigned int ulp_icd_start, ulp_num = 0;  	phba->io_sgl_hndl_avbl = 0;  	phba->eh_sgl_hndl_avbl = 0; @@ -3336,8 +4044,8 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)  						 phba->params.ios_per_ctrl,  						 GFP_KERNEL);  		if (!phba->io_sgl_hndl_base) { -			shost_printk(KERN_ERR, phba->shost, -				     "Mem Alloc Failed. Failing to load\n"); +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : Mem Alloc Failed. Failing to load\n");  			return -ENOMEM;  		}  		phba->eh_sgl_hndl_base = kzalloc(sizeof(struct sgl_handle *) * @@ -3346,14 +4054,14 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)  						 GFP_KERNEL);  		if (!phba->eh_sgl_hndl_base) {  			kfree(phba->io_sgl_hndl_base); -			shost_printk(KERN_ERR, phba->shost, -				     "Mem Alloc Failed. Failing to load\n"); +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +				    "BM_%d : Mem Alloc Failed. Failing to load\n");  			return -ENOMEM;  		}  	} else { -		shost_printk(KERN_ERR, phba->shost, -			     "HWI_MEM_SGLH is more than one element." -			     "Failing to load\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : HWI_MEM_SGLH is more than one element." +			    "Failing to load\n");  		return -ENOMEM;  	} @@ -3379,15 +4087,24 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)  		}  		idx++;  	} -	SE_DEBUG(DBG_LVL_8, -		 "phba->io_sgl_hndl_avbl=%d" -		 "phba->eh_sgl_hndl_avbl=%d\n", -		 phba->io_sgl_hndl_avbl, -		 phba->eh_sgl_hndl_avbl); +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "BM_%d : phba->io_sgl_hndl_avbl=%d" +		    "phba->eh_sgl_hndl_avbl=%d\n", +		    phba->io_sgl_hndl_avbl, +		    phba->eh_sgl_hndl_avbl); +  	mem_descr_sg = phba->init_mem;  	mem_descr_sg += HWI_MEM_SGE; -	SE_DEBUG(DBG_LVL_8, "\n mem_descr_sg->num_elements=%d\n", -		 mem_descr_sg->num_elements); +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "\n BM_%d : mem_descr_sg->num_elements=%d\n", +		    mem_descr_sg->num_elements); + +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) +		if (test_bit(ulp_num, &phba->fw_config.ulp_supported)) +			break; + +	ulp_icd_start = phba->fw_config.iscsi_icd_start[ulp_num]; +  	arr_index = 0;  	idx = 0;  	while (idx < mem_descr_sg->num_elements) { @@ -3406,8 +4123,7 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)  			AMAP_SET_BITS(struct amap_iscsi_sge, addr_hi, pfrag, 0);  			AMAP_SET_BITS(struct amap_iscsi_sge, addr_lo, pfrag, 0);  			pfrag += phba->params.num_sge_per_io; -			psgl_handle->sgl_index = -				phba->fw_config.iscsi_icd_start + arr_index++; +			psgl_handle->sgl_index = ulp_icd_start + arr_index++;  		}  		idx++;  	} @@ -3420,32 +4136,105 @@ static int beiscsi_init_sgl_handle(struct beiscsi_hba *phba)  static int hba_setup_cid_tbls(struct beiscsi_hba *phba)  { -	int i, new_cid; - -	phba->cid_array = kzalloc(sizeof(void *) * phba->params.cxns_per_ctrl, -				  GFP_KERNEL); -	if (!phba->cid_array) { -		shost_printk(KERN_ERR, phba->shost, -			     "Failed to allocate memory in " -			     "hba_setup_cid_tbls\n"); -		return -ENOMEM; +	int ret; +	uint16_t i, ulp_num; +	struct ulp_cid_info *ptr_cid_info = NULL; + +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { +			ptr_cid_info = kzalloc(sizeof(struct ulp_cid_info), +					       GFP_KERNEL); + +			if (!ptr_cid_info) { +				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +					    "BM_%d : Failed to allocate memory" +					    "for ULP_CID_INFO for ULP : %d\n", +					    ulp_num); +				ret = -ENOMEM; +				goto free_memory; + +			} + +			/* Allocate memory for CID array */ +			ptr_cid_info->cid_array = kzalloc(sizeof(void *) * +						  BEISCSI_GET_CID_COUNT(phba, +						  ulp_num), GFP_KERNEL); +			if (!ptr_cid_info->cid_array) { +				beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +					    "BM_%d : Failed to allocate memory" +					    "for CID_ARRAY for ULP : %d\n", +					    ulp_num); +				kfree(ptr_cid_info); +				ptr_cid_info = NULL; +				ret = -ENOMEM; + +				goto free_memory; +			} +			ptr_cid_info->avlbl_cids = BEISCSI_GET_CID_COUNT( +						   phba, ulp_num); + +			/* Save the cid_info_array ptr */ +			phba->cid_array_info[ulp_num] = ptr_cid_info; +		}  	}  	phba->ep_array = kzalloc(sizeof(struct iscsi_endpoint *) * -				 phba->params.cxns_per_ctrl * 2, GFP_KERNEL); +				 phba->params.cxns_per_ctrl, GFP_KERNEL);  	if (!phba->ep_array) { -		shost_printk(KERN_ERR, phba->shost, -			     "Failed to allocate memory in " -			     "hba_setup_cid_tbls\n"); -		kfree(phba->cid_array); -		return -ENOMEM; +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Failed to allocate memory in " +			    "hba_setup_cid_tbls\n"); +		ret = -ENOMEM; + +		goto free_memory; +	} + +	phba->conn_table = kzalloc(sizeof(struct beiscsi_conn *) * +				   phba->params.cxns_per_ctrl, GFP_KERNEL); +	if (!phba->conn_table) { +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Failed to allocate memory in" +			    "hba_setup_cid_tbls\n"); + +		kfree(phba->ep_array); +		phba->ep_array = NULL; +		ret = -ENOMEM; + +		goto free_memory;  	} -	new_cid = phba->fw_config.iscsi_cid_start; +  	for (i = 0; i < phba->params.cxns_per_ctrl; i++) { -		phba->cid_array[i] = new_cid; -		new_cid += 2; +		ulp_num = phba->phwi_ctrlr->wrb_context[i].ulp_num; + +		ptr_cid_info = phba->cid_array_info[ulp_num]; +		ptr_cid_info->cid_array[ptr_cid_info->cid_alloc++] = +			phba->phwi_ctrlr->wrb_context[i].cid; + +	} + +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { +			ptr_cid_info = phba->cid_array_info[ulp_num]; + +			ptr_cid_info->cid_alloc = 0; +			ptr_cid_info->cid_free = 0; +		}  	} -	phba->avlbl_cids = phba->params.cxns_per_ctrl;  	return 0; + +free_memory: +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { +			ptr_cid_info = phba->cid_array_info[ulp_num]; + +			if (ptr_cid_info) { +				kfree(ptr_cid_info->cid_array); +				kfree(ptr_cid_info); +				phba->cid_array_info[ulp_num] = NULL; +			} +		} +	} + +	return ret;  }  static void hwi_enable_intr(struct beiscsi_hba *phba) @@ -3464,23 +4253,27 @@ static void hwi_enable_intr(struct beiscsi_hba *phba)  	addr = (u8 __iomem *) ((u8 __iomem *) ctrl->pcicfg +  			PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET);  	reg = ioread32(addr); -	SE_DEBUG(DBG_LVL_8, "reg =x%08x\n", reg);  	enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;  	if (!enabled) {  		reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; -		SE_DEBUG(DBG_LVL_8, "reg =x%08x addr=%p\n", reg, addr); +		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +			    "BM_%d : reg =x%08x addr=%p\n", reg, addr);  		iowrite32(reg, addr); -		if (!phba->msix_enabled) { -			eq = &phwi_context->be_eq[0].q; -			SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id); +	} + +	if (!phba->msix_enabled) { +		eq = &phwi_context->be_eq[0].q; +		beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +			    "BM_%d : eq->id=%d\n", eq->id); + +		hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); +	} else { +		for (i = 0; i <= phba->num_cpus; i++) { +			eq = &phwi_context->be_eq[i].q; +			beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +				    "BM_%d : eq->id=%d\n", eq->id);  			hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); -		} else { -			for (i = 0; i <= phba->num_cpus; i++) { -				eq = &phwi_context->be_eq[i].q; -				SE_DEBUG(DBG_LVL_8, "eq->id=%d\n", eq->id); -				hwi_ring_eq_db(phba, eq->id, 0, 0, 1, 1); -			}  		}  	}  } @@ -3497,90 +4290,137 @@ static void hwi_disable_intr(struct beiscsi_hba *phba)  		reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK;  		iowrite32(reg, addr);  	} else -		shost_printk(KERN_WARNING, phba->shost, -			     "In hwi_disable_intr, Already Disabled\n"); +		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, +			    "BM_%d : In hwi_disable_intr, Already Disabled\n");  } +/** + * beiscsi_get_boot_info()- Get the boot session info + * @phba: The device priv structure instance + * + * Get the boot target info and store in driver priv structure + * + * return values + *	Success: 0 + *	Failure: Non-Zero Value + **/  static int beiscsi_get_boot_info(struct beiscsi_hba *phba)  { -	struct be_cmd_resp_get_boot_target *boot_resp; -	struct be_cmd_resp_get_session *session_resp; -	struct be_mcc_wrb *wrb; +	struct be_cmd_get_session_resp *session_resp;  	struct be_dma_mem nonemb_cmd; -	unsigned int tag, wrb_num; -	unsigned short status, extd_status; -	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q; - -	tag = beiscsi_get_boot_target(phba); -	if (!tag) { -		SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed\n"); -		return -EAGAIN; -	} else -		wait_event_interruptible(phba->ctrl.mcc_wait[tag], -					 phba->ctrl.mcc_numtag[tag]); - -	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; -	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; -	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; -	if (status || extd_status) { -		SE_DEBUG(DBG_LVL_1, "be_cmd_get_mac_addr Failed" -				    " status = %d extd_status = %d\n", -				    status, extd_status); -		free_mcc_tag(&phba->ctrl, tag); -		return -EBUSY; -	} -	wrb = queue_get_wrb(mccq, wrb_num); -	free_mcc_tag(&phba->ctrl, tag); -	boot_resp = embedded_payload(wrb); +	unsigned int tag; +	unsigned int s_handle; +	int ret = -ENOMEM; -	if (boot_resp->boot_session_handle < 0) { -		printk(KERN_ERR "No Boot Session for this pci_func," -			"session Hndl = %d\n", boot_resp->boot_session_handle); -		return -ENXIO; +	/* Get the session handle of the boot target */ +	ret = be_mgmt_get_boot_shandle(phba, &s_handle); +	if (ret) { +		beiscsi_log(phba, KERN_ERR, +			    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, +			    "BM_%d : No boot session\n"); +		return ret;  	} -  	nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,  				sizeof(*session_resp),  				&nonemb_cmd.dma);  	if (nonemb_cmd.va == NULL) { -		SE_DEBUG(DBG_LVL_1, -			 "Failed to allocate memory for" -			 "beiscsi_get_session_info\n"); +		beiscsi_log(phba, KERN_ERR, +			    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, +			    "BM_%d : Failed to allocate memory for" +			    "beiscsi_get_session_info\n"); +  		return -ENOMEM;  	}  	memset(nonemb_cmd.va, 0, sizeof(*session_resp)); -	tag = beiscsi_get_session_info(phba, -		boot_resp->boot_session_handle, &nonemb_cmd); +	tag = mgmt_get_session_info(phba, s_handle, +				    &nonemb_cmd);  	if (!tag) { -		SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info" -			" Failed\n"); -		goto boot_freemem; -	} else -		wait_event_interruptible(phba->ctrl.mcc_wait[tag], -					 phba->ctrl.mcc_numtag[tag]); - -	wrb_num = (phba->ctrl.mcc_numtag[tag] & 0x00FF0000) >> 16; -	extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; -	status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; -	if (status || extd_status) { -		SE_DEBUG(DBG_LVL_1, "beiscsi_get_session_info Failed" -				    " status = %d extd_status = %d\n", -				    status, extd_status); -		free_mcc_tag(&phba->ctrl, tag); +		beiscsi_log(phba, KERN_ERR, +			    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, +			    "BM_%d : beiscsi_get_session_info" +			    " Failed\n"); +  		goto boot_freemem;  	} -	wrb = queue_get_wrb(mccq, wrb_num); -	free_mcc_tag(&phba->ctrl, tag); + +	ret = beiscsi_mccq_compl(phba, tag, NULL, &nonemb_cmd); +	if (ret) { +		beiscsi_log(phba, KERN_ERR, +			    BEISCSI_LOG_INIT | BEISCSI_LOG_CONFIG, +			    "BM_%d : beiscsi_get_session_info Failed"); + +		if (ret != -EBUSY) +			goto boot_freemem; +		else +			return ret; +	} +  	session_resp = nonemb_cmd.va ; +  	memcpy(&phba->boot_sess, &session_resp->session_info,  	       sizeof(struct mgmt_session_info)); -	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, -		    nonemb_cmd.va, nonemb_cmd.dma); -	return 0; +	ret = 0; +  boot_freemem:  	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,  		    nonemb_cmd.va, nonemb_cmd.dma); +	return ret; +} + +static void beiscsi_boot_release(void *data) +{ +	struct beiscsi_hba *phba = data; + +	scsi_host_put(phba->shost); +} + +static int beiscsi_setup_boot_info(struct beiscsi_hba *phba) +{ +	struct iscsi_boot_kobj *boot_kobj; + +	/* get boot info using mgmt cmd */ +	if (beiscsi_get_boot_info(phba)) +		/* Try to see if we can carry on without this */ +		return 0; + +	phba->boot_kset = iscsi_boot_create_host_kset(phba->shost->host_no); +	if (!phba->boot_kset) +		return -ENOMEM; + +	/* get a ref because the show function will ref the phba */ +	if (!scsi_host_get(phba->shost)) +		goto free_kset; +	boot_kobj = iscsi_boot_create_target(phba->boot_kset, 0, phba, +					     beiscsi_show_boot_tgt_info, +					     beiscsi_tgt_get_attr_visibility, +					     beiscsi_boot_release); +	if (!boot_kobj) +		goto put_shost; + +	if (!scsi_host_get(phba->shost)) +		goto free_kset; +	boot_kobj = iscsi_boot_create_initiator(phba->boot_kset, 0, phba, +						beiscsi_show_boot_ini_info, +						beiscsi_ini_get_attr_visibility, +						beiscsi_boot_release); +	if (!boot_kobj) +		goto put_shost; + +	if (!scsi_host_get(phba->shost)) +		goto free_kset; +	boot_kobj = iscsi_boot_create_ethernet(phba->boot_kset, 0, phba, +					       beiscsi_show_boot_eth_info, +					       beiscsi_eth_get_attr_visibility, +					       beiscsi_boot_release); +	if (!boot_kobj) +		goto put_shost; +	return 0; + +put_shost: +	scsi_host_put(phba->shost); +free_kset: +	iscsi_boot_destroy_kset(phba->boot_kset);  	return -ENOMEM;  } @@ -3590,22 +4430,22 @@ static int beiscsi_init_port(struct beiscsi_hba *phba)  	ret = beiscsi_init_controller(phba);  	if (ret < 0) { -		shost_printk(KERN_ERR, phba->shost, -			     "beiscsi_dev_probe - Failed in" -			     "beiscsi_init_controller\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : beiscsi_dev_probe - Failed in" +			    "beiscsi_init_controller\n");  		return ret;  	}  	ret = beiscsi_init_sgl_handle(phba);  	if (ret < 0) { -		shost_printk(KERN_ERR, phba->shost, -			     "beiscsi_dev_probe - Failed in" -			     "beiscsi_init_sgl_handle\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : beiscsi_dev_probe - Failed in" +			    "beiscsi_init_sgl_handle\n");  		goto do_cleanup_ctrlr;  	}  	if (hba_setup_cid_tbls(phba)) { -		shost_printk(KERN_ERR, phba->shost, -			     "Failed in hba_setup_cid_tbls\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Failed in hba_setup_cid_tbls\n");  		kfree(phba->io_sgl_hndl_base);  		kfree(phba->eh_sgl_hndl_base);  		goto do_cleanup_ctrlr; @@ -3653,19 +4493,135 @@ static void hwi_purge_eq(struct beiscsi_hba *phba)  static void beiscsi_clean_port(struct beiscsi_hba *phba)  { -	int mgmt_status; - -	mgmt_status = mgmt_epfw_cleanup(phba, CMD_CONNECTION_CHUTE_0); -	if (mgmt_status) -		shost_printk(KERN_WARNING, phba->shost, -			     "mgmt_epfw_cleanup FAILED\n"); +	int mgmt_status, ulp_num; +	struct ulp_cid_info *ptr_cid_info = NULL; + +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { +			mgmt_status = mgmt_epfw_cleanup(phba, ulp_num); +			if (mgmt_status) +				beiscsi_log(phba, KERN_WARNING, +					    BEISCSI_LOG_INIT, +					    "BM_%d : mgmt_epfw_cleanup FAILED" +					    " for ULP_%d\n", ulp_num); +		} +	}  	hwi_purge_eq(phba);  	hwi_cleanup(phba);  	kfree(phba->io_sgl_hndl_base);  	kfree(phba->eh_sgl_hndl_base); -	kfree(phba->cid_array);  	kfree(phba->ep_array); +	kfree(phba->conn_table); + +	for (ulp_num = 0; ulp_num < BEISCSI_ULP_COUNT; ulp_num++) { +		if (test_bit(ulp_num, (void *)&phba->fw_config.ulp_supported)) { +			ptr_cid_info = phba->cid_array_info[ulp_num]; + +			if (ptr_cid_info) { +				kfree(ptr_cid_info->cid_array); +				kfree(ptr_cid_info); +				phba->cid_array_info[ulp_num] = NULL; +			} +		} +	} + +} + +/** + * beiscsi_free_mgmt_task_handles()- Free driver CXN resources + * @beiscsi_conn: ptr to the conn to be cleaned up + * @task: ptr to iscsi_task resource to be freed. + * + * Free driver mgmt resources binded to CXN. + **/ +void +beiscsi_free_mgmt_task_handles(struct beiscsi_conn *beiscsi_conn, +				struct iscsi_task *task) +{ +	struct beiscsi_io_task *io_task; +	struct beiscsi_hba *phba = beiscsi_conn->phba; +	struct hwi_wrb_context *pwrb_context; +	struct hwi_controller *phwi_ctrlr; +	uint16_t cri_index = BE_GET_CRI_FROM_CID( +				beiscsi_conn->beiscsi_conn_cid); + +	phwi_ctrlr = phba->phwi_ctrlr; +	pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; + +	io_task = task->dd_data; + +	if (io_task->pwrb_handle) { +		memset(io_task->pwrb_handle->pwrb, 0, +		       sizeof(struct iscsi_wrb)); +		free_wrb_handle(phba, pwrb_context, +				io_task->pwrb_handle); +		io_task->pwrb_handle = NULL; +	} + +	if (io_task->psgl_handle) { +		spin_lock_bh(&phba->mgmt_sgl_lock); +		free_mgmt_sgl_handle(phba, +				     io_task->psgl_handle); +		io_task->psgl_handle = NULL; +		spin_unlock_bh(&phba->mgmt_sgl_lock); +	} + +	if (io_task->mtask_addr) +		pci_unmap_single(phba->pcidev, +				 io_task->mtask_addr, +				 io_task->mtask_data_count, +				 PCI_DMA_TODEVICE); +} + +/** + * beiscsi_cleanup_task()- Free driver resources of the task + * @task: ptr to the iscsi task + * + **/ +static void beiscsi_cleanup_task(struct iscsi_task *task) +{ +	struct beiscsi_io_task *io_task = task->dd_data; +	struct iscsi_conn *conn = task->conn; +	struct beiscsi_conn *beiscsi_conn = conn->dd_data; +	struct beiscsi_hba *phba = beiscsi_conn->phba; +	struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; +	struct hwi_wrb_context *pwrb_context; +	struct hwi_controller *phwi_ctrlr; +	uint16_t cri_index = BE_GET_CRI_FROM_CID( +			     beiscsi_conn->beiscsi_conn_cid); + +	phwi_ctrlr = phba->phwi_ctrlr; +	pwrb_context = &phwi_ctrlr->wrb_context[cri_index]; + +	if (io_task->cmd_bhs) { +		pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, +			      io_task->bhs_pa.u.a64.address); +		io_task->cmd_bhs = NULL; +	} + +	if (task->sc) { +		if (io_task->pwrb_handle) { +			free_wrb_handle(phba, pwrb_context, +					io_task->pwrb_handle); +			io_task->pwrb_handle = NULL; +		} + +		if (io_task->psgl_handle) { +			spin_lock(&phba->io_sgl_lock); +			free_io_sgl_handle(phba, io_task->psgl_handle); +			spin_unlock(&phba->io_sgl_lock); +			io_task->psgl_handle = NULL; +		} + +		if (io_task->scsi_cmnd) { +			scsi_dma_unmap(io_task->scsi_cmnd); +			io_task->scsi_cmnd = NULL; +		} +	} else { +		if (!beiscsi_conn->login_in_progress) +			beiscsi_free_mgmt_task_handles(beiscsi_conn, task); +	}  }  void @@ -3673,85 +4629,38 @@ beiscsi_offload_connection(struct beiscsi_conn *beiscsi_conn,  			   struct beiscsi_offload_params *params)  {  	struct wrb_handle *pwrb_handle; -	struct iscsi_target_context_update_wrb *pwrb = NULL; -	struct be_mem_descriptor *mem_descr;  	struct beiscsi_hba *phba = beiscsi_conn->phba; +	struct iscsi_task *task = beiscsi_conn->task; +	struct iscsi_session *session = task->conn->session;  	u32 doorbell = 0;  	/*  	 * We can always use 0 here because it is reserved by libiscsi for  	 * login/startup related tasks.  	 */ -	pwrb_handle = alloc_wrb_handle(phba, (beiscsi_conn->beiscsi_conn_cid - -				       phba->fw_config.iscsi_cid_start)); -	pwrb = (struct iscsi_target_context_update_wrb *)pwrb_handle->pwrb; -	memset(pwrb, 0, sizeof(*pwrb)); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, -		      max_burst_length, pwrb, params->dw[offsetof -		      (struct amap_beiscsi_offload_params, -		      max_burst_length) / 32]); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, -		      max_send_data_segment_length, pwrb, -		      params->dw[offsetof(struct amap_beiscsi_offload_params, -		      max_send_data_segment_length) / 32]); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, -		      first_burst_length, -		      pwrb, -		      params->dw[offsetof(struct amap_beiscsi_offload_params, -		      first_burst_length) / 32]); - -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, erl, pwrb, -		      (params->dw[offsetof(struct amap_beiscsi_offload_params, -		      erl) / 32] & OFFLD_PARAMS_ERL)); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, dde, pwrb, -		      (params->dw[offsetof(struct amap_beiscsi_offload_params, -		      dde) / 32] & OFFLD_PARAMS_DDE) >> 2); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, hde, pwrb, -		      (params->dw[offsetof(struct amap_beiscsi_offload_params, -		      hde) / 32] & OFFLD_PARAMS_HDE) >> 3); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ir2t, pwrb, -		      (params->dw[offsetof(struct amap_beiscsi_offload_params, -		      ir2t) / 32] & OFFLD_PARAMS_IR2T) >> 4); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, imd, pwrb, -		      (params->dw[offsetof(struct amap_beiscsi_offload_params, -		       imd) / 32] & OFFLD_PARAMS_IMD) >> 5); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, stat_sn, -		      pwrb, -		      (params->dw[offsetof(struct amap_beiscsi_offload_params, -		      exp_statsn) / 32] + 1)); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, type, pwrb, -		      0x7); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, wrb_idx, -		      pwrb, pwrb_handle->wrb_index); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, ptr2nextwrb, -		      pwrb, pwrb_handle->nxt_wrb_index); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, -			session_state, pwrb, 0); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, compltonack, -		      pwrb, 1); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, notpredblq, -		      pwrb, 0); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, mode, pwrb, -		      0); +	beiscsi_conn->login_in_progress = 0; +	spin_lock_bh(&session->back_lock); +	beiscsi_cleanup_task(task); +	spin_unlock_bh(&session->back_lock); -	mem_descr = phba->init_mem; -	mem_descr += ISCSI_MEM_GLOBAL_HEADER; +	pwrb_handle = alloc_wrb_handle(phba, beiscsi_conn->beiscsi_conn_cid); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, -			pad_buffer_addr_hi, pwrb, -		      mem_descr->mem_array[0].bus_address.u.a32.address_hi); -	AMAP_SET_BITS(struct amap_iscsi_target_context_update_wrb, -			pad_buffer_addr_lo, pwrb, -		      mem_descr->mem_array[0].bus_address.u.a32.address_lo); +	/* Check for the adapter family */ +	if (is_chip_be2_be3r(phba)) +		beiscsi_offload_cxn_v0(params, pwrb_handle, +				       phba->init_mem); +	else +		beiscsi_offload_cxn_v2(params, pwrb_handle); -	be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_target_context_update_wrb)); +	be_dws_le_to_cpu(pwrb_handle->pwrb, +			 sizeof(struct iscsi_target_context_update_wrb));  	doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK;  	doorbell |= (pwrb_handle->wrb_index & DB_DEF_PDU_WRB_INDEX_MASK)  			     << DB_DEF_PDU_WRB_INDEX_SHIFT;  	doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; - -	iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); +	iowrite32(doorbell, phba->db_va + +		  beiscsi_conn->doorbell_offset);  }  static void beiscsi_parse_pdu(struct iscsi_conn *conn, itt_t itt, @@ -3781,11 +4690,12 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)  	struct hwi_wrb_context *pwrb_context;  	struct hwi_controller *phwi_ctrlr;  	itt_t itt; +	uint16_t cri_index = 0;  	struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess;  	dma_addr_t paddr;  	io_task->cmd_bhs = pci_pool_alloc(beiscsi_sess->bhs_pool, -					  GFP_KERNEL, &paddr); +					  GFP_ATOMIC, &paddr);  	if (!io_task->cmd_bhs)  		return -ENOMEM;  	io_task->bhs_pa.u.a64.address = paddr; @@ -3795,39 +4705,66 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)  	task->hdr = (struct iscsi_hdr *)&io_task->cmd_bhs->iscsi_hdr;  	task->hdr_max = sizeof(struct be_cmd_bhs);  	io_task->psgl_handle = NULL; -	io_task->psgl_handle = NULL; +	io_task->pwrb_handle = NULL;  	if (task->sc) {  		spin_lock(&phba->io_sgl_lock);  		io_task->psgl_handle = alloc_io_sgl_handle(phba);  		spin_unlock(&phba->io_sgl_lock); -		if (!io_task->psgl_handle) +		if (!io_task->psgl_handle) { +			beiscsi_log(phba, KERN_ERR, +				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +				    "BM_%d : Alloc of IO_SGL_ICD Failed" +				    "for the CID : %d\n", +				    beiscsi_conn->beiscsi_conn_cid);  			goto free_hndls; +		}  		io_task->pwrb_handle = alloc_wrb_handle(phba, -					beiscsi_conn->beiscsi_conn_cid - -					phba->fw_config.iscsi_cid_start); -		if (!io_task->pwrb_handle) +					beiscsi_conn->beiscsi_conn_cid); +		if (!io_task->pwrb_handle) { +			beiscsi_log(phba, KERN_ERR, +				    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +				    "BM_%d : Alloc of WRB_HANDLE Failed" +				    "for the CID : %d\n", +				    beiscsi_conn->beiscsi_conn_cid);  			goto free_io_hndls; +		}  	} else {  		io_task->scsi_cmnd = NULL;  		if ((opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) { +			beiscsi_conn->task = task;  			if (!beiscsi_conn->login_in_progress) {  				spin_lock(&phba->mgmt_sgl_lock);  				io_task->psgl_handle = (struct sgl_handle *)  						alloc_mgmt_sgl_handle(phba);  				spin_unlock(&phba->mgmt_sgl_lock); -				if (!io_task->psgl_handle) +				if (!io_task->psgl_handle) { +					beiscsi_log(phba, KERN_ERR, +						    BEISCSI_LOG_IO | +						    BEISCSI_LOG_CONFIG, +						    "BM_%d : Alloc of MGMT_SGL_ICD Failed" +						    "for the CID : %d\n", +						    beiscsi_conn-> +						    beiscsi_conn_cid);  					goto free_hndls; +				}  				beiscsi_conn->login_in_progress = 1;  				beiscsi_conn->plogin_sgl_handle =  							io_task->psgl_handle;  				io_task->pwrb_handle =  					alloc_wrb_handle(phba, -					beiscsi_conn->beiscsi_conn_cid - -					phba->fw_config.iscsi_cid_start); -				if (!io_task->pwrb_handle) -					goto free_io_hndls; +					beiscsi_conn->beiscsi_conn_cid); +				if (!io_task->pwrb_handle) { +					beiscsi_log(phba, KERN_ERR, +						    BEISCSI_LOG_IO | +						    BEISCSI_LOG_CONFIG, +						    "BM_%d : Alloc of WRB_HANDLE Failed" +						    "for the CID : %d\n", +						    beiscsi_conn-> +						    beiscsi_conn_cid); +					goto free_mgmt_hndls; +				}  				beiscsi_conn->plogin_wrb_handle =  							io_task->pwrb_handle; @@ -3841,14 +4778,27 @@ static int beiscsi_alloc_pdu(struct iscsi_task *task, uint8_t opcode)  			spin_lock(&phba->mgmt_sgl_lock);  			io_task->psgl_handle = alloc_mgmt_sgl_handle(phba);  			spin_unlock(&phba->mgmt_sgl_lock); -			if (!io_task->psgl_handle) +			if (!io_task->psgl_handle) { +				beiscsi_log(phba, KERN_ERR, +					    BEISCSI_LOG_IO | +					    BEISCSI_LOG_CONFIG, +					    "BM_%d : Alloc of MGMT_SGL_ICD Failed" +					    "for the CID : %d\n", +					    beiscsi_conn-> +					    beiscsi_conn_cid);  				goto free_hndls; +			}  			io_task->pwrb_handle =  					alloc_wrb_handle(phba, -					beiscsi_conn->beiscsi_conn_cid - -					phba->fw_config.iscsi_cid_start); -			if (!io_task->pwrb_handle) +					beiscsi_conn->beiscsi_conn_cid); +			if (!io_task->pwrb_handle) { +				beiscsi_log(phba, KERN_ERR, +					    BEISCSI_LOG_IO | BEISCSI_LOG_CONFIG, +					    "BM_%d : Alloc of WRB_HANDLE Failed" +					    "for the CID : %d\n", +					    beiscsi_conn->beiscsi_conn_cid);  				goto free_mgmt_hndls; +			}  		}  	} @@ -3868,61 +4818,76 @@ free_io_hndls:  free_mgmt_hndls:  	spin_lock(&phba->mgmt_sgl_lock);  	free_mgmt_sgl_handle(phba, io_task->psgl_handle); +	io_task->psgl_handle = NULL;  	spin_unlock(&phba->mgmt_sgl_lock);  free_hndls:  	phwi_ctrlr = phba->phwi_ctrlr; -	pwrb_context = &phwi_ctrlr->wrb_context[ -			beiscsi_conn->beiscsi_conn_cid - -			phba->fw_config.iscsi_cid_start]; +	cri_index = BE_GET_CRI_FROM_CID( +	beiscsi_conn->beiscsi_conn_cid); +	pwrb_context = &phwi_ctrlr->wrb_context[cri_index];  	if (io_task->pwrb_handle)  		free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle);  	io_task->pwrb_handle = NULL;  	pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs,  		      io_task->bhs_pa.u.a64.address); -	SE_DEBUG(DBG_LVL_1, "Alloc of SGL_ICD Failed\n"); +	io_task->cmd_bhs = NULL;  	return -ENOMEM;  } - -static void beiscsi_cleanup_task(struct iscsi_task *task) +int beiscsi_iotask_v2(struct iscsi_task *task, struct scatterlist *sg, +		       unsigned int num_sg, unsigned int xferlen, +		       unsigned int writedir)  { +  	struct beiscsi_io_task *io_task = task->dd_data;  	struct iscsi_conn *conn = task->conn;  	struct beiscsi_conn *beiscsi_conn = conn->dd_data;  	struct beiscsi_hba *phba = beiscsi_conn->phba; -	struct beiscsi_session *beiscsi_sess = beiscsi_conn->beiscsi_sess; -	struct hwi_wrb_context *pwrb_context; -	struct hwi_controller *phwi_ctrlr; +	struct iscsi_wrb *pwrb = NULL; +	unsigned int doorbell = 0; -	phwi_ctrlr = phba->phwi_ctrlr; -	pwrb_context = &phwi_ctrlr->wrb_context[beiscsi_conn->beiscsi_conn_cid -			- phba->fw_config.iscsi_cid_start]; -	if (io_task->pwrb_handle) { -		free_wrb_handle(phba, pwrb_context, io_task->pwrb_handle); -		io_task->pwrb_handle = NULL; -	} +	pwrb = io_task->pwrb_handle->pwrb; -	if (io_task->cmd_bhs) { -		pci_pool_free(beiscsi_sess->bhs_pool, io_task->cmd_bhs, -			      io_task->bhs_pa.u.a64.address); -	} +	io_task->cmd_bhs->iscsi_hdr.exp_statsn = 0; +	io_task->bhs_len = sizeof(struct be_cmd_bhs); -	if (task->sc) { -		if (io_task->psgl_handle) { -			spin_lock(&phba->io_sgl_lock); -			free_io_sgl_handle(phba, io_task->psgl_handle); -			spin_unlock(&phba->io_sgl_lock); -			io_task->psgl_handle = NULL; -		} +	if (writedir) { +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb, +			      INI_WR_CMD); +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 1);  	} else { -		if ((task->hdr->opcode & ISCSI_OPCODE_MASK) == ISCSI_OP_LOGIN) -			return; -		if (io_task->psgl_handle) { -			spin_lock(&phba->mgmt_sgl_lock); -			free_mgmt_sgl_handle(phba, io_task->psgl_handle); -			spin_unlock(&phba->mgmt_sgl_lock); -			io_task->psgl_handle = NULL; -		} +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, type, pwrb, +			      INI_RD_CMD); +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, dsp, pwrb, 0);  	} + +	io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb_v2, +					  type, pwrb); + +	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, lun, pwrb, +		      cpu_to_be16(*(unsigned short *) +		      &io_task->cmd_bhs->iscsi_hdr.lun)); +	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, xferlen); +	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb, +		      io_task->pwrb_handle->wrb_index); +	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb, +		      be32_to_cpu(task->cmdsn)); +	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb, +		      io_task->psgl_handle->sgl_index); + +	hwi_write_sgl_v2(pwrb, sg, num_sg, io_task); +	AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, +		      io_task->pwrb_handle->nxt_wrb_index); + +	be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); + +	doorbell |= beiscsi_conn->beiscsi_conn_cid & DB_WRB_POST_CID_MASK; +	doorbell |= (io_task->pwrb_handle->wrb_index & +		     DB_DEF_PDU_WRB_INDEX_MASK) << +		     DB_DEF_PDU_WRB_INDEX_SHIFT; +	doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; +	iowrite32(doorbell, phba->db_va + +		  beiscsi_conn->doorbell_offset); +	return 0;  }  static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg, @@ -3942,15 +4907,6 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,  	io_task->bhs_len = sizeof(struct be_cmd_bhs);  	if (writedir) { -		memset(&io_task->cmd_bhs->iscsi_data_pdu, 0, 48); -		AMAP_SET_BITS(struct amap_pdu_data_out, itt, -			      &io_task->cmd_bhs->iscsi_data_pdu, -			      (unsigned int)io_task->cmd_bhs->iscsi_hdr.itt); -		AMAP_SET_BITS(struct amap_pdu_data_out, opcode, -			      &io_task->cmd_bhs->iscsi_data_pdu, -			      ISCSI_OPCODE_SCSI_DATA_OUT); -		AMAP_SET_BITS(struct amap_pdu_data_out, final_bit, -			      &io_task->cmd_bhs->iscsi_data_pdu, 1);  		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb,  			      INI_WR_CMD);  		AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 1); @@ -3959,13 +4915,13 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,  			      INI_RD_CMD);  		AMAP_SET_BITS(struct amap_iscsi_wrb, dsp, pwrb, 0);  	} -	memcpy(&io_task->cmd_bhs->iscsi_data_pdu. -	       dw[offsetof(struct amap_pdu_data_out, lun) / 32], -	       io_task->cmd_bhs->iscsi_hdr.lun, sizeof(struct scsi_lun)); + +	io_task->wrb_type = AMAP_GET_BITS(struct amap_iscsi_wrb, +					  type, pwrb);  	AMAP_SET_BITS(struct amap_iscsi_wrb, lun, pwrb, -		      cpu_to_be16((unsigned short)io_task->cmd_bhs->iscsi_hdr. -				  lun[0])); +		      cpu_to_be16(*(unsigned short *) +				  &io_task->cmd_bhs->iscsi_hdr.lun));  	AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, xferlen);  	AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb,  		      io_task->pwrb_handle->wrb_index); @@ -3985,7 +4941,8 @@ static int beiscsi_iotask(struct iscsi_task *task, struct scatterlist *sg,  		     DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT;  	doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; -	iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); +	iowrite32(doorbell, phba->db_va + +		  beiscsi_conn->doorbell_offset);  	return 0;  } @@ -3998,70 +4955,97 @@ static int beiscsi_mtask(struct iscsi_task *task)  	struct iscsi_wrb *pwrb = NULL;  	unsigned int doorbell = 0;  	unsigned int cid; +	unsigned int pwrb_typeoffset = 0;  	cid = beiscsi_conn->beiscsi_conn_cid;  	pwrb = io_task->pwrb_handle->pwrb;  	memset(pwrb, 0, sizeof(*pwrb)); -	AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, -		      be32_to_cpu(task->cmdsn)); -	AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, -		      io_task->pwrb_handle->wrb_index); -	AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, -		      io_task->psgl_handle->sgl_index); + +	if (is_chip_be2_be3r(phba)) { +		AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, +			      be32_to_cpu(task->cmdsn)); +		AMAP_SET_BITS(struct amap_iscsi_wrb, wrb_idx, pwrb, +			      io_task->pwrb_handle->wrb_index); +		AMAP_SET_BITS(struct amap_iscsi_wrb, sgl_icd_idx, pwrb, +			      io_task->psgl_handle->sgl_index); +		AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, +			      task->data_count); +		AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, +			      io_task->pwrb_handle->nxt_wrb_index); +		pwrb_typeoffset = BE_WRB_TYPE_OFFSET; +	} else { +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, cmdsn_itt, pwrb, +			      be32_to_cpu(task->cmdsn)); +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, wrb_idx, pwrb, +			      io_task->pwrb_handle->wrb_index); +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, sgl_idx, pwrb, +			      io_task->psgl_handle->sgl_index); +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, r2t_exp_dtl, pwrb, +			      task->data_count); +		AMAP_SET_BITS(struct amap_iscsi_wrb_v2, ptr2nextwrb, pwrb, +			      io_task->pwrb_handle->nxt_wrb_index); +		pwrb_typeoffset = SKH_WRB_TYPE_OFFSET; +	} +  	switch (task->hdr->opcode & ISCSI_OPCODE_MASK) {  	case ISCSI_OP_LOGIN: -		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, -			      TGT_DM_CMD); -		AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0);  		AMAP_SET_BITS(struct amap_iscsi_wrb, cmdsn_itt, pwrb, 1); +		ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);  		hwi_write_buffer(pwrb, task);  		break;  	case ISCSI_OP_NOOP_OUT: -		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, -			      INI_RD_CMD); -		if (task->hdr->ttt == ISCSI_RESERVED_TAG) -			AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); -		else -			AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 1); +		if (task->hdr->ttt != ISCSI_RESERVED_TAG) { +			ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset); +			if (is_chip_be2_be3r(phba)) +				AMAP_SET_BITS(struct amap_iscsi_wrb, +					      dmsg, pwrb, 1); +			else +				AMAP_SET_BITS(struct amap_iscsi_wrb_v2, +					      dmsg, pwrb, 1); +		} else { +			ADAPTER_SET_WRB_TYPE(pwrb, INI_RD_CMD, pwrb_typeoffset); +			if (is_chip_be2_be3r(phba)) +				AMAP_SET_BITS(struct amap_iscsi_wrb, +					      dmsg, pwrb, 0); +			else +				AMAP_SET_BITS(struct amap_iscsi_wrb_v2, +					      dmsg, pwrb, 0); +		}  		hwi_write_buffer(pwrb, task);  		break;  	case ISCSI_OP_TEXT: -		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, -			      TGT_DM_CMD); -		AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); +		ADAPTER_SET_WRB_TYPE(pwrb, TGT_DM_CMD, pwrb_typeoffset);  		hwi_write_buffer(pwrb, task);  		break;  	case ISCSI_OP_SCSI_TMFUNC: -		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, -			      INI_TMF_CMD); -		AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); +		ADAPTER_SET_WRB_TYPE(pwrb, INI_TMF_CMD, pwrb_typeoffset);  		hwi_write_buffer(pwrb, task);  		break;  	case ISCSI_OP_LOGOUT: -		AMAP_SET_BITS(struct amap_iscsi_wrb, dmsg, pwrb, 0); -		AMAP_SET_BITS(struct amap_iscsi_wrb, type, pwrb, -			      HWH_TYPE_LOGOUT); +		ADAPTER_SET_WRB_TYPE(pwrb, HWH_TYPE_LOGOUT, pwrb_typeoffset);  		hwi_write_buffer(pwrb, task);  		break;  	default: -		SE_DEBUG(DBG_LVL_1, "opcode =%d Not supported\n", -			 task->hdr->opcode & ISCSI_OPCODE_MASK); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, +			    "BM_%d : opcode =%d Not supported\n", +			    task->hdr->opcode & ISCSI_OPCODE_MASK); +  		return -EINVAL;  	} -	AMAP_SET_BITS(struct amap_iscsi_wrb, r2t_exp_dtl, pwrb, -		      task->data_count); -	AMAP_SET_BITS(struct amap_iscsi_wrb, ptr2nextwrb, pwrb, -		      io_task->pwrb_handle->nxt_wrb_index); -	be_dws_le_to_cpu(pwrb, sizeof(struct iscsi_wrb)); +	/* Set the task type */ +	io_task->wrb_type = (is_chip_be2_be3r(phba)) ? +		AMAP_GET_BITS(struct amap_iscsi_wrb, type, pwrb) : +		AMAP_GET_BITS(struct amap_iscsi_wrb_v2, type, pwrb);  	doorbell |= cid & DB_WRB_POST_CID_MASK;  	doorbell |= (io_task->pwrb_handle->wrb_index &  		     DB_DEF_PDU_WRB_INDEX_MASK) << DB_DEF_PDU_WRB_INDEX_SHIFT;  	doorbell |= 1 << DB_DEF_PDU_NUM_POSTED_SHIFT; -	iowrite32(doorbell, phba->db_va + DB_TXULP0_OFFSET); +	iowrite32(doorbell, phba->db_va + +		  beiscsi_conn->doorbell_offset);  	return 0;  } @@ -4069,45 +5053,144 @@ static int beiscsi_task_xmit(struct iscsi_task *task)  {  	struct beiscsi_io_task *io_task = task->dd_data;  	struct scsi_cmnd *sc = task->sc; +	struct beiscsi_hba *phba = NULL;  	struct scatterlist *sg;  	int num_sg;  	unsigned int  writedir = 0, xferlen = 0; +	phba = ((struct beiscsi_conn *)task->conn->dd_data)->phba; +  	if (!sc)  		return beiscsi_mtask(task);  	io_task->scsi_cmnd = sc;  	num_sg = scsi_dma_map(sc);  	if (num_sg < 0) { -		SE_DEBUG(DBG_LVL_1, " scsi_dma_map Failed\n") +		struct iscsi_conn *conn = task->conn; +		struct beiscsi_hba *phba = NULL; + +		phba = ((struct beiscsi_conn *)conn->dd_data)->phba; +		beiscsi_log(phba, KERN_ERR, +			    BEISCSI_LOG_IO | BEISCSI_LOG_ISCSI, +			    "BM_%d : scsi_dma_map Failed " +			    "Driver_ITT : 0x%x ITT : 0x%x Xferlen : 0x%x\n", +			    be32_to_cpu(io_task->cmd_bhs->iscsi_hdr.itt), +			    io_task->libiscsi_itt, scsi_bufflen(sc)); +  		return num_sg;  	}  	xferlen = scsi_bufflen(sc);  	sg = scsi_sglist(sc); -	if (sc->sc_data_direction == DMA_TO_DEVICE) { +	if (sc->sc_data_direction == DMA_TO_DEVICE)  		writedir = 1; -		SE_DEBUG(DBG_LVL_4, "task->imm_count=0x%08x\n", -			 task->imm_count); -	} else +	 else  		writedir = 0; -	return beiscsi_iotask(task, sg, num_sg, xferlen, writedir); + +	 return phba->iotask_fn(task, sg, num_sg, xferlen, writedir);  } -static void beiscsi_remove(struct pci_dev *pcidev) +/** + * beiscsi_bsg_request - handle bsg request from ISCSI transport + * @job: job to handle + */ +static int beiscsi_bsg_request(struct bsg_job *job) +{ +	struct Scsi_Host *shost; +	struct beiscsi_hba *phba; +	struct iscsi_bsg_request *bsg_req = job->request; +	int rc = -EINVAL; +	unsigned int tag; +	struct be_dma_mem nonemb_cmd; +	struct be_cmd_resp_hdr *resp; +	struct iscsi_bsg_reply *bsg_reply = job->reply; +	unsigned short status, extd_status; + +	shost = iscsi_job_to_shost(job); +	phba = iscsi_host_priv(shost); + +	switch (bsg_req->msgcode) { +	case ISCSI_BSG_HST_VENDOR: +		nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev, +					job->request_payload.payload_len, +					&nonemb_cmd.dma); +		if (nonemb_cmd.va == NULL) { +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, +				    "BM_%d : Failed to allocate memory for " +				    "beiscsi_bsg_request\n"); +			return -ENOMEM; +		} +		tag = mgmt_vendor_specific_fw_cmd(&phba->ctrl, phba, job, +						  &nonemb_cmd); +		if (!tag) { +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, +				    "BM_%d : MBX Tag Allocation Failed\n"); + +			pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, +					    nonemb_cmd.va, nonemb_cmd.dma); +			return -EAGAIN; +		} + +		rc = wait_event_interruptible_timeout( +					phba->ctrl.mcc_wait[tag], +					phba->ctrl.mcc_numtag[tag], +					msecs_to_jiffies( +					BEISCSI_HOST_MBX_TIMEOUT)); +		extd_status = (phba->ctrl.mcc_numtag[tag] & 0x0000FF00) >> 8; +		status = phba->ctrl.mcc_numtag[tag] & 0x000000FF; +		free_mcc_tag(&phba->ctrl, tag); +		resp = (struct be_cmd_resp_hdr *)nonemb_cmd.va; +		sg_copy_from_buffer(job->reply_payload.sg_list, +				    job->reply_payload.sg_cnt, +				    nonemb_cmd.va, (resp->response_length +				    + sizeof(*resp))); +		bsg_reply->reply_payload_rcv_len = resp->response_length; +		bsg_reply->result = status; +		bsg_job_done(job, bsg_reply->result, +			     bsg_reply->reply_payload_rcv_len); +		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size, +				    nonemb_cmd.va, nonemb_cmd.dma); +		if (status || extd_status) { +			beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, +				    "BM_%d : MBX Cmd Failed" +				    " status = %d extd_status = %d\n", +				    status, extd_status); + +			return -EIO; +		} else { +			rc = 0; +		} +		break; + +	default: +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG, +				"BM_%d : Unsupported bsg command: 0x%x\n", +				bsg_req->msgcode); +		break; +	} + +	return rc; +} + +void beiscsi_hba_attrs_init(struct beiscsi_hba *phba) +{ +	/* Set the logging parameter */ +	beiscsi_log_enable_init(phba, beiscsi_log_enable); +} + +/* + * beiscsi_quiesce()- Cleanup Driver resources + * @phba: Instance Priv structure + * @unload_state:i Clean or EEH unload state + * + * Free the OS and HW resources held by the driver + **/ +static void beiscsi_quiesce(struct beiscsi_hba *phba, +		uint32_t unload_state)  { -	struct beiscsi_hba *phba = NULL;  	struct hwi_controller *phwi_ctrlr;  	struct hwi_context_memory *phwi_context;  	struct be_eq_obj *pbe_eq;  	unsigned int i, msix_vec; -	u8 *real_offset = 0; -	u32 value = 0; - -	phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); -	if (!phba) { -		dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n"); -		return; -	}  	phwi_ctrlr = phba->phwi_ctrlr;  	phwi_context = phwi_ctrlr->phwi_ctxt; @@ -4115,38 +5198,77 @@ static void beiscsi_remove(struct pci_dev *pcidev)  	if (phba->msix_enabled) {  		for (i = 0; i <= phba->num_cpus; i++) {  			msix_vec = phba->msix_entries[i].vector; +			synchronize_irq(msix_vec);  			free_irq(msix_vec, &phwi_context->be_eq[i]); +			kfree(phba->msi_name[i]);  		}  	} else -		if (phba->pcidev->irq) +		if (phba->pcidev->irq) { +			synchronize_irq(phba->pcidev->irq);  			free_irq(phba->pcidev->irq, phba); -	pci_disable_msix(phba->pcidev); -	destroy_workqueue(phba->wq); -	if (blk_iopoll_enabled) -		for (i = 0; i < phba->num_cpus; i++) { -			pbe_eq = &phwi_context->be_eq[i]; -			blk_iopoll_disable(&pbe_eq->iopoll);  		} +	pci_disable_msix(phba->pcidev); -	beiscsi_clean_port(phba); -	beiscsi_free_mem(phba); -	real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; +	for (i = 0; i < phba->num_cpus; i++) { +		pbe_eq = &phwi_context->be_eq[i]; +		blk_iopoll_disable(&pbe_eq->iopoll); +	} -	value = readl((void *)real_offset); +	if (unload_state == BEISCSI_CLEAN_UNLOAD) { +		destroy_workqueue(phba->wq); +		beiscsi_clean_port(phba); +		beiscsi_free_mem(phba); -	if (value & 0x00010000) { -		value &= 0xfffeffff; -		writel(value, (void *)real_offset); +		beiscsi_unmap_pci_function(phba); +		pci_free_consistent(phba->pcidev, +				    phba->ctrl.mbox_mem_alloced.size, +				    phba->ctrl.mbox_mem_alloced.va, +				    phba->ctrl.mbox_mem_alloced.dma); +	} else { +		hwi_purge_eq(phba); +		hwi_cleanup(phba);  	} -	beiscsi_unmap_pci_function(phba); -	pci_free_consistent(phba->pcidev, -			    phba->ctrl.mbox_mem_alloced.size, -			    phba->ctrl.mbox_mem_alloced.va, -			    phba->ctrl.mbox_mem_alloced.dma); + +	cancel_delayed_work_sync(&phba->beiscsi_hw_check_task); +} + +static void beiscsi_remove(struct pci_dev *pcidev) +{ + +	struct beiscsi_hba *phba = NULL; + +	phba = pci_get_drvdata(pcidev); +	if (!phba) { +		dev_err(&pcidev->dev, "beiscsi_remove called with no phba\n"); +		return; +	} + +	beiscsi_destroy_def_ifaces(phba); +	beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); +	iscsi_boot_destroy_kset(phba->boot_kset);  	iscsi_host_remove(phba->shost);  	pci_dev_put(phba->pcidev);  	iscsi_host_free(phba->shost); -	iscsi_boot_destroy_kset(phba->boot_kset); +	pci_disable_pcie_error_reporting(pcidev); +	pci_set_drvdata(pcidev, NULL); +	pci_disable_device(pcidev); +} + +static void beiscsi_shutdown(struct pci_dev *pcidev) +{ + +	struct beiscsi_hba *phba = NULL; + +	phba = (struct beiscsi_hba *)pci_get_drvdata(pcidev); +	if (!phba) { +		dev_err(&pcidev->dev, "beiscsi_shutdown called with no phba\n"); +		return; +	} + +	phba->state = BE_ADAPTER_STATE_SHUTDOWN; +	iscsi_host_for_each_session(phba->shost, be2iscsi_fail_session); +	beiscsi_quiesce(phba, BEISCSI_CLEAN_UNLOAD); +	pci_disable_device(pcidev);  }  static void beiscsi_msix_enable(struct beiscsi_hba *phba) @@ -4164,172 +5286,420 @@ static void beiscsi_msix_enable(struct beiscsi_hba *phba)  	return;  } -static int __devinit beiscsi_dev_probe(struct pci_dev *pcidev, -				const struct pci_device_id *id) +static void be_eqd_update(struct beiscsi_hba *phba) +{ +	struct be_set_eqd set_eqd[MAX_CPUS]; +	struct be_aic_obj *aic; +	struct be_eq_obj *pbe_eq; +	struct hwi_controller *phwi_ctrlr; +	struct hwi_context_memory *phwi_context; +	int eqd, i, num = 0; +	ulong now; +	u32 pps, delta; +	unsigned int tag; + +	phwi_ctrlr = phba->phwi_ctrlr; +	phwi_context = phwi_ctrlr->phwi_ctxt; + +	for (i = 0; i <= phba->num_cpus; i++) { +		aic = &phba->aic_obj[i]; +		pbe_eq = &phwi_context->be_eq[i]; +		now = jiffies; +		if (!aic->jiffs || time_before(now, aic->jiffs) || +		    pbe_eq->cq_count < aic->eq_prev) { +			aic->jiffs = now; +			aic->eq_prev = pbe_eq->cq_count; +			continue; +		} +		delta = jiffies_to_msecs(now - aic->jiffs); +		pps = (((u32)(pbe_eq->cq_count - aic->eq_prev) * 1000) / delta); +		eqd = (pps / 1500) << 2; + +		if (eqd < 8) +			eqd = 0; +		eqd = min_t(u32, eqd, phwi_context->max_eqd); +		eqd = max_t(u32, eqd, phwi_context->min_eqd); + +		aic->jiffs = now; +		aic->eq_prev = pbe_eq->cq_count; + +		if (eqd != aic->prev_eqd) { +			set_eqd[num].delay_multiplier = (eqd * 65)/100; +			set_eqd[num].eq_id = pbe_eq->q.id; +			aic->prev_eqd = eqd; +			num++; +		} +	} +	if (num) { +		tag = be_cmd_modify_eq_delay(phba, set_eqd, num); +		if (tag) +			beiscsi_mccq_compl(phba, tag, NULL, NULL); +	} +} + +/* + * beiscsi_hw_health_check()- Check adapter health + * @work: work item to check HW health + * + * Check if adapter in an unrecoverable state or not. + **/ +static void +beiscsi_hw_health_check(struct work_struct *work) +{ +	struct beiscsi_hba *phba = +		container_of(work, struct beiscsi_hba, +			     beiscsi_hw_check_task.work); + +	be_eqd_update(phba); + +	beiscsi_ue_detect(phba); + +	schedule_delayed_work(&phba->beiscsi_hw_check_task, +			      msecs_to_jiffies(1000)); +} + + +static pci_ers_result_t beiscsi_eeh_err_detected(struct pci_dev *pdev, +		pci_channel_state_t state) +{ +	struct beiscsi_hba *phba = NULL; + +	phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); +	phba->state |= BE_ADAPTER_PCI_ERR; + +	beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +		    "BM_%d : EEH error detected\n"); + +	beiscsi_quiesce(phba, BEISCSI_EEH_UNLOAD); + +	if (state == pci_channel_io_perm_failure) { +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : EEH : State PERM Failure"); +		return PCI_ERS_RESULT_DISCONNECT; +	} + +	pci_disable_device(pdev); + +	/* The error could cause the FW to trigger a flash debug dump. +	 * Resetting the card while flash dump is in progress +	 * can cause it not to recover; wait for it to finish. +	 * Wait only for first function as it is needed only once per +	 * adapter. +	 **/ +	if (pdev->devfn == 0) +		ssleep(30); + +	return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t beiscsi_eeh_reset(struct pci_dev *pdev) +{ +	struct beiscsi_hba *phba = NULL; +	int status = 0; + +	phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); + +	beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +		    "BM_%d : EEH Reset\n"); + +	status = pci_enable_device(pdev); +	if (status) +		return PCI_ERS_RESULT_DISCONNECT; + +	pci_set_master(pdev); +	pci_set_power_state(pdev, PCI_D0); +	pci_restore_state(pdev); + +	/* Wait for the CHIP Reset to complete */ +	status = be_chk_reset_complete(phba); +	if (!status) { +		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, +			    "BM_%d : EEH Reset Completed\n"); +	} else { +		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, +			    "BM_%d : EEH Reset Completion Failure\n"); +		return PCI_ERS_RESULT_DISCONNECT; +	} + +	pci_cleanup_aer_uncorrect_error_status(pdev); +	return PCI_ERS_RESULT_RECOVERED; +} + +static void beiscsi_eeh_resume(struct pci_dev *pdev) +{ +	int ret = 0, i; +	struct be_eq_obj *pbe_eq; +	struct beiscsi_hba *phba = NULL; +	struct hwi_controller *phwi_ctrlr; +	struct hwi_context_memory *phwi_context; + +	phba = (struct beiscsi_hba *)pci_get_drvdata(pdev); +	pci_save_state(pdev); + +	if (enable_msix) +		find_num_cpus(phba); +	else +		phba->num_cpus = 1; + +	if (enable_msix) { +		beiscsi_msix_enable(phba); +		if (!phba->msix_enabled) +			phba->num_cpus = 1; +	} + +	ret = beiscsi_cmd_reset_function(phba); +	if (ret) { +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Reset Failed\n"); +		goto ret_err; +	} + +	ret = be_chk_reset_complete(phba); +	if (ret) { +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Failed to get out of reset.\n"); +		goto ret_err; +	} + +	beiscsi_get_params(phba); +	phba->shost->max_id = phba->params.cxns_per_ctrl; +	phba->shost->can_queue = phba->params.ios_per_ctrl; +	ret = hwi_init_controller(phba); + +	for (i = 0; i < MAX_MCC_CMD; i++) { +		init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]); +		phba->ctrl.mcc_tag[i] = i + 1; +		phba->ctrl.mcc_numtag[i + 1] = 0; +		phba->ctrl.mcc_tag_available++; +	} + +	phwi_ctrlr = phba->phwi_ctrlr; +	phwi_context = phwi_ctrlr->phwi_ctxt; + +	for (i = 0; i < phba->num_cpus; i++) { +		pbe_eq = &phwi_context->be_eq[i]; +		blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, +				be_iopoll); +		blk_iopoll_enable(&pbe_eq->iopoll); +	} + +	i = (phba->msix_enabled) ? i : 0; +	/* Work item for MCC handling */ +	pbe_eq = &phwi_context->be_eq[i]; +	INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs); + +	ret = beiscsi_init_irqs(phba); +	if (ret < 0) { +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : beiscsi_eeh_resume - " +			    "Failed to beiscsi_init_irqs\n"); +		goto ret_err; +	} + +	hwi_enable_intr(phba); +	phba->state &= ~BE_ADAPTER_PCI_ERR; + +	return; +ret_err: +	beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +		    "BM_%d : AER EEH Resume Failed\n"); +} + +static int beiscsi_dev_probe(struct pci_dev *pcidev, +			     const struct pci_device_id *id)  {  	struct beiscsi_hba *phba = NULL;  	struct hwi_controller *phwi_ctrlr;  	struct hwi_context_memory *phwi_context;  	struct be_eq_obj *pbe_eq; -	int ret, num_cpus, i; -	u8 *real_offset = 0; -	u32 value = 0; +	int ret = 0, i;  	ret = beiscsi_enable_pci(pcidev);  	if (ret < 0) { -		dev_err(&pcidev->dev, "beiscsi_dev_probe-" -			" Failed to enable pci device\n"); +		dev_err(&pcidev->dev, +			"beiscsi_dev_probe - Failed to enable pci device\n");  		return ret;  	}  	phba = beiscsi_hba_alloc(pcidev);  	if (!phba) { -		dev_err(&pcidev->dev, "beiscsi_dev_probe-" -			" Failed in beiscsi_hba_alloc\n"); +		dev_err(&pcidev->dev, +			"beiscsi_dev_probe - Failed in beiscsi_hba_alloc\n");  		goto disable_pci;  	} +	/* Enable EEH reporting */ +	ret = pci_enable_pcie_error_reporting(pcidev); +	if (ret) +		beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_INIT, +			    "BM_%d : PCIe Error Reporting " +			    "Enabling Failed\n"); + +	pci_save_state(pcidev); + +	/* Initialize Driver configuration Paramters */ +	beiscsi_hba_attrs_init(phba); + +	phba->fw_timeout = false; +	phba->mac_addr_set = false; + +  	switch (pcidev->device) {  	case BE_DEVICE_ID1:  	case OC_DEVICE_ID1:  	case OC_DEVICE_ID2:  		phba->generation = BE_GEN2; +		phba->iotask_fn = beiscsi_iotask;  		break;  	case BE_DEVICE_ID2:  	case OC_DEVICE_ID3:  		phba->generation = BE_GEN3; +		phba->iotask_fn = beiscsi_iotask; +		break; +	case OC_SKH_ID1: +		phba->generation = BE_GEN4; +		phba->iotask_fn = beiscsi_iotask_v2;  		break;  	default:  		phba->generation = 0;  	} -	if (enable_msix) -		num_cpus = find_num_cpus(); -	else -		num_cpus = 1; -	phba->num_cpus = num_cpus; -	SE_DEBUG(DBG_LVL_8, "num_cpus = %d\n", phba->num_cpus); - -	if (enable_msix) -		beiscsi_msix_enable(phba);  	ret = be_ctrl_init(phba, pcidev);  	if (ret) { -		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" -				"Failed in be_ctrl_init\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : beiscsi_dev_probe-" +			    "Failed in be_ctrl_init\n");  		goto hba_free;  	} -	if (!num_hba) { -		real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; -		value = readl((void *)real_offset); -		if (value & 0x00010000) { -			gcrashmode++; -			shost_printk(KERN_ERR, phba->shost, -				"Loading Driver in crashdump mode\n"); -			ret = beiscsi_pci_soft_reset(phba); -			if (ret) { -				shost_printk(KERN_ERR, phba->shost, -					"Reset Failed. Aborting Crashdump\n"); -				goto hba_free; -			} -			ret = be_chk_reset_complete(phba); -			if (ret) { -				shost_printk(KERN_ERR, phba->shost, -					"Failed to get out of reset." -					"Aborting Crashdump\n"); -				goto hba_free; -			} -		} else { -			value |= 0x00010000; -			writel(value, (void *)real_offset); -			num_hba++; -		} +	ret = beiscsi_cmd_reset_function(phba); +	if (ret) { +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Reset Failed\n"); +		goto hba_free; +	} +	ret = be_chk_reset_complete(phba); +	if (ret) { +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Failed to get out of reset.\n"); +		goto hba_free;  	}  	spin_lock_init(&phba->io_sgl_lock);  	spin_lock_init(&phba->mgmt_sgl_lock);  	spin_lock_init(&phba->isr_lock); +	spin_lock_init(&phba->async_pdu_lock);  	ret = mgmt_get_fw_config(&phba->ctrl, phba);  	if (ret != 0) { -		shost_printk(KERN_ERR, phba->shost, -			     "Error getting fw config\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Error getting fw config\n");  		goto free_port;  	} -	phba->shost->max_id = phba->fw_config.iscsi_cid_count; + +	if (enable_msix) +		find_num_cpus(phba); +	else +		phba->num_cpus = 1; + +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "BM_%d : num_cpus = %d\n", +		    phba->num_cpus); + +	if (enable_msix) { +		beiscsi_msix_enable(phba); +		if (!phba->msix_enabled) +			phba->num_cpus = 1; +	} + +	phba->shost->max_id = phba->params.cxns_per_ctrl;  	beiscsi_get_params(phba);  	phba->shost->can_queue = phba->params.ios_per_ctrl;  	ret = beiscsi_init_port(phba);  	if (ret < 0) { -		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" -			     "Failed in beiscsi_init_port\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : beiscsi_dev_probe-" +			    "Failed in beiscsi_init_port\n");  		goto free_port;  	} -	for (i = 0; i < MAX_MCC_CMD ; i++) { +	for (i = 0; i < MAX_MCC_CMD; i++) {  		init_waitqueue_head(&phba->ctrl.mcc_wait[i + 1]);  		phba->ctrl.mcc_tag[i] = i + 1;  		phba->ctrl.mcc_numtag[i + 1] = 0;  		phba->ctrl.mcc_tag_available++; +		memset(&phba->ctrl.ptag_state[i].tag_mem_state, 0, +		       sizeof(struct be_dma_mem));  	}  	phba->ctrl.mcc_alloc_index = phba->ctrl.mcc_free_index = 0; -	snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u", +	snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_%02x_wq",  		 phba->shost->host_no); -	phba->wq = create_workqueue(phba->wq_name); +	phba->wq = alloc_workqueue("%s", WQ_MEM_RECLAIM, 1, phba->wq_name);  	if (!phba->wq) { -		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" -				"Failed to allocate work queue\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : beiscsi_dev_probe-" +			    "Failed to allocate work queue\n");  		goto free_twq;  	} -	INIT_WORK(&phba->work_cqs, beiscsi_process_all_cqs); +	INIT_DELAYED_WORK(&phba->beiscsi_hw_check_task, +			  beiscsi_hw_health_check);  	phwi_ctrlr = phba->phwi_ctrlr;  	phwi_context = phwi_ctrlr->phwi_ctxt; -	if (blk_iopoll_enabled) { -		for (i = 0; i < phba->num_cpus; i++) { -			pbe_eq = &phwi_context->be_eq[i]; -			blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, -					be_iopoll); -			blk_iopoll_enable(&pbe_eq->iopoll); -		} + +	for (i = 0; i < phba->num_cpus; i++) { +		pbe_eq = &phwi_context->be_eq[i]; +		blk_iopoll_init(&pbe_eq->iopoll, be_iopoll_budget, +				be_iopoll); +		blk_iopoll_enable(&pbe_eq->iopoll);  	} + +	i = (phba->msix_enabled) ? i : 0; +	/* Work item for MCC handling */ +	pbe_eq = &phwi_context->be_eq[i]; +	INIT_WORK(&pbe_eq->work_cqs, beiscsi_process_all_cqs); +  	ret = beiscsi_init_irqs(phba);  	if (ret < 0) { -		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" -			     "Failed to beiscsi_init_irqs\n"); +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : beiscsi_dev_probe-" +			    "Failed to beiscsi_init_irqs\n");  		goto free_blkenbld;  	}  	hwi_enable_intr(phba); -	ret = beiscsi_get_boot_info(phba); -	if (ret < 0) { -		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-" -			     "No Boot Devices !!!!!\n"); -	} -	SE_DEBUG(DBG_LVL_8, "\n\n\n SUCCESS - DRIVER LOADED\n\n\n"); + +	if (iscsi_host_add(phba->shost, &phba->pcidev->dev)) +		goto free_blkenbld; + +	if (beiscsi_setup_boot_info(phba)) +		/* +		 * log error but continue, because we may not be using +		 * iscsi boot. +		 */ +		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT, +			    "BM_%d : Could not set up " +			    "iSCSI boot info.\n"); + +	beiscsi_create_def_ifaces(phba); +	schedule_delayed_work(&phba->beiscsi_hw_check_task, +			      msecs_to_jiffies(1000)); + +	beiscsi_log(phba, KERN_INFO, BEISCSI_LOG_INIT, +		    "\n\n\n BM_%d : SUCCESS - DRIVER LOADED\n\n\n");  	return 0;  free_blkenbld:  	destroy_workqueue(phba->wq); -	if (blk_iopoll_enabled) -		for (i = 0; i < phba->num_cpus; i++) { -			pbe_eq = &phwi_context->be_eq[i]; -			blk_iopoll_disable(&pbe_eq->iopoll); -		} +	for (i = 0; i < phba->num_cpus; i++) { +		pbe_eq = &phwi_context->be_eq[i]; +		blk_iopoll_disable(&pbe_eq->iopoll); +	}  free_twq:  	beiscsi_clean_port(phba);  	beiscsi_free_mem(phba);  free_port: -	real_offset = (u8 *)phba->csr_va + MPU_EP_SEMAPHORE; - -	value = readl((void *)real_offset); - -	if (value & 0x00010000) { -		value &= 0xfffeffff; -		writel(value, (void *)real_offset); -	} -  	pci_free_consistent(phba->pcidev,  			    phba->ctrl.mbox_mem_alloced.size,  			    phba->ctrl.mbox_mem_alloced.va, @@ -4346,44 +5716,27 @@ disable_pci:  	return ret;  } +static struct pci_error_handlers beiscsi_eeh_handlers = { +	.error_detected = beiscsi_eeh_err_detected, +	.slot_reset = beiscsi_eeh_reset, +	.resume = beiscsi_eeh_resume, +}; +  struct iscsi_transport beiscsi_iscsi_transport = {  	.owner = THIS_MODULE,  	.name = DRV_NAME,  	.caps = CAP_RECOVERY_L0 | CAP_HDRDGST | CAP_TEXT_NEGO |  		CAP_MULTI_R2T | CAP_DATADGST | CAP_DATA_PATH_OFFLOAD, -	.param_mask = ISCSI_MAX_RECV_DLENGTH | -		ISCSI_MAX_XMIT_DLENGTH | -		ISCSI_HDRDGST_EN | -		ISCSI_DATADGST_EN | -		ISCSI_INITIAL_R2T_EN | -		ISCSI_MAX_R2T | -		ISCSI_IMM_DATA_EN | -		ISCSI_FIRST_BURST | -		ISCSI_MAX_BURST | -		ISCSI_PDU_INORDER_EN | -		ISCSI_DATASEQ_INORDER_EN | -		ISCSI_ERL | -		ISCSI_CONN_PORT | -		ISCSI_CONN_ADDRESS | -		ISCSI_EXP_STATSN | -		ISCSI_PERSISTENT_PORT | -		ISCSI_PERSISTENT_ADDRESS | -		ISCSI_TARGET_NAME | ISCSI_TPGT | -		ISCSI_USERNAME | ISCSI_PASSWORD | -		ISCSI_USERNAME_IN | ISCSI_PASSWORD_IN | -		ISCSI_FAST_ABORT | ISCSI_ABORT_TMO | -		ISCSI_LU_RESET_TMO | -		ISCSI_PING_TMO | ISCSI_RECV_TMO | -		ISCSI_IFACE_NAME | ISCSI_INITIATOR_NAME, -	.host_param_mask = ISCSI_HOST_HWADDRESS | ISCSI_HOST_IPADDRESS | -				ISCSI_HOST_INITIATOR_NAME,  	.create_session = beiscsi_session_create,  	.destroy_session = beiscsi_session_destroy,  	.create_conn = beiscsi_conn_create,  	.bind_conn = beiscsi_conn_bind,  	.destroy_conn = iscsi_conn_teardown, +	.attr_is_visible = be2iscsi_attr_is_visible, +	.set_iface_param = be2iscsi_iface_set_param, +	.get_iface_param = be2iscsi_iface_get_param,  	.set_param = beiscsi_set_param, -	.get_conn_param = beiscsi_conn_get_param, +	.get_conn_param = iscsi_conn_get_param,  	.get_session_param = iscsi_session_get_param,  	.get_host_param = beiscsi_get_host_param,  	.start_conn = beiscsi_conn_start, @@ -4394,17 +5747,21 @@ struct iscsi_transport beiscsi_iscsi_transport = {  	.alloc_pdu = beiscsi_alloc_pdu,  	.parse_pdu_itt = beiscsi_parse_pdu,  	.get_stats = beiscsi_conn_get_stats, +	.get_ep_param = beiscsi_ep_get_param,  	.ep_connect = beiscsi_ep_connect,  	.ep_poll = beiscsi_ep_poll,  	.ep_disconnect = beiscsi_ep_disconnect,  	.session_recovery_timedout = iscsi_session_recovery_timedout, +	.bsg_request = beiscsi_bsg_request,  };  static struct pci_driver beiscsi_pci_driver = {  	.name = DRV_NAME,  	.probe = beiscsi_dev_probe,  	.remove = beiscsi_remove, -	.id_table = beiscsi_pci_id_table +	.shutdown = beiscsi_shutdown, +	.id_table = beiscsi_pci_id_table, +	.err_handler = &beiscsi_eeh_handlers  }; @@ -4415,19 +5772,17 @@ static int __init beiscsi_module_init(void)  	beiscsi_scsi_transport =  			iscsi_register_transport(&beiscsi_iscsi_transport);  	if (!beiscsi_scsi_transport) { -		SE_DEBUG(DBG_LVL_1, -			 "beiscsi_module_init - Unable to  register beiscsi" -			 "transport.\n"); +		printk(KERN_ERR +		       "beiscsi_module_init - Unable to  register beiscsi transport.\n");  		return -ENOMEM;  	} -	SE_DEBUG(DBG_LVL_8, "In beiscsi_module_init, tt=%p\n", -		 &beiscsi_iscsi_transport); +	printk(KERN_INFO "In beiscsi_module_init, tt=%p\n", +	       &beiscsi_iscsi_transport);  	ret = pci_register_driver(&beiscsi_pci_driver);  	if (ret) { -		SE_DEBUG(DBG_LVL_1, -			 "beiscsi_module_init - Unable to  register" -			 "beiscsi pci driver.\n"); +		printk(KERN_ERR +		       "beiscsi_module_init - Unable to  register beiscsi pci driver.\n");  		goto unregister_iscsi_transport;  	}  	return 0;  | 
