Beispiel #1
0
/**
 * beiscsi_ep_connect - Ask chip to create TCP Conn
 * @scsi_host: Pointer to scsi_host structure
 * @dst_addr: The IP address of Target
 * @non_blocking: blocking or non-blocking call
 *
 * This routines first asks chip to create a connection and then allocates an EP
 */
struct iscsi_endpoint *
beiscsi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
		   int non_blocking)
{
	struct beiscsi_hba *phba;
	struct beiscsi_endpoint *beiscsi_ep;
	struct iscsi_endpoint *ep;
	int ret;

	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_connect \n");
	if (shost)
		phba = iscsi_host_priv(shost);
	else {
		ret = -ENXIO;
		SE_DEBUG(DBG_LVL_1, "shost is NULL \n");
		return ERR_PTR(ret);
	}

	if (phba->state != BE_ADAPTER_UP) {
		ret = -EBUSY;
		SE_DEBUG(DBG_LVL_1, "The Adapter state is Not UP \n");
		return ERR_PTR(ret);
	}

	ep = iscsi2_create_endpoint(sizeof(struct beiscsi_endpoint));
	if (!ep) {
		ret = -ENOMEM;
		return ERR_PTR(ret);
	}

	beiscsi_ep = ep->dd_data;
	beiscsi_ep->phba = phba;
	beiscsi_ep->openiscsi_ep = ep;
	if (beiscsi_open_conn(ep, NULL, dst_addr, non_blocking)) {
		SE_DEBUG(DBG_LVL_1, "Failed in beiscsi_open_conn \n");
		ret = -ENOMEM;
		goto free_ep;
	}

	return ep;

free_ep:
	beiscsi_free_ep(beiscsi_ep);
	return ERR_PTR(ret);
}
/**
 * beiscsi_ep_disconnect - Tears down the TCP connection
 * @ep:	endpoint to be used
 *
 * Tears down the TCP connection
 */
void beiscsi_ep_disconnect(struct iscsi_endpoint *ep)
{
	struct beiscsi_conn *beiscsi_conn;
	struct beiscsi_endpoint *beiscsi_ep;
	struct beiscsi_hba *phba;
	unsigned int tag;
	unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;

	beiscsi_ep = ep->dd_data;
	phba = beiscsi_ep->phba;
	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect for ep_cid = %d\n",
			     beiscsi_ep->ep_cid);

	if (!beiscsi_ep->conn) {
		SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect, no "
			 "beiscsi_ep\n");
		return;
	}
	beiscsi_conn = beiscsi_ep->conn;
	iscsi_suspend_queue(beiscsi_conn->conn);

	SE_DEBUG(DBG_LVL_8, "In beiscsi_ep_disconnect ep_cid = %d\n",
		 beiscsi_ep->ep_cid);

	tag = mgmt_invalidate_connection(phba, beiscsi_ep,
					    beiscsi_ep->ep_cid, 1,
					    savecfg_flag);
	if (!tag) {
		SE_DEBUG(DBG_LVL_1,
			 "mgmt_invalidate_connection Failed for cid=%d\n",
			  beiscsi_ep->ep_cid);
	} else {
		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
					 phba->ctrl.mcc_numtag[tag]);
		free_mcc_tag(&phba->ctrl, tag);
	}

	beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL);
	beiscsi_free_ep(beiscsi_ep);
	beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
	iscsi_destroy_endpoint(beiscsi_ep->openiscsi_ep);
}
Beispiel #3
0
/**
 * beiscsi_conn_stop - Invalidate and stop the connection
 * @cls_conn: pointer to get iscsi_conn
 * @flag: The type of connection closure
 */
void beiscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag)
{
	struct iscsi_conn *conn = cls_conn->dd_data;
	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
	struct beiscsi_endpoint *beiscsi_ep;
	struct iscsi_session *session = conn->session;
	struct Scsi_Host *shost = iscsi_session_to_shost(session->cls_session);
	struct beiscsi_hba *phba = iscsi_host_priv(shost);
	unsigned int tag;
	unsigned short savecfg_flag = CMD_ISCSI_SESSION_SAVE_CFG_ON_FLASH;

	beiscsi_ep = beiscsi_conn->ep;
	if (!beiscsi_ep) {
		SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop , no beiscsi_ep\n");
		return;
	}
	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop  ep_cid = %d\n",
			     beiscsi_ep->ep_cid);
	tag = mgmt_invalidate_connection(phba, beiscsi_ep,
					    beiscsi_ep->ep_cid, 0,
					    savecfg_flag);
	if (!tag) {
		SE_DEBUG(DBG_LVL_1,
			 "mgmt_invalidate_connection Failed for cid=%d \n",
			 beiscsi_ep->ep_cid);
	} else {
		wait_event_interruptible(phba->ctrl.mcc_wait[tag],
					 phba->ctrl.mcc_numtag[tag]);
		free_mcc_tag(&phba->ctrl, tag);
	}
	beiscsi_close_conn(beiscsi_ep, CONNECTION_UPLOAD_GRACEFUL);
	beiscsi_free_ep(beiscsi_ep);
	iscsi2_destroy_endpoint(beiscsi_ep->openiscsi_ep);
	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_stop for ep_cid = %d\n", beiscsi_ep->ep_cid);
	beiscsi_unbind_conn_to_cid(phba, beiscsi_ep->ep_cid);
	iscsi2_conn_stop(cls_conn, flag);
}
/**
 * beiscsi_open_conn - Ask FW to open a TCP connection
 * @ep:	endpoint to be used
 * @src_addr: The source IP address
 * @dst_addr: The Destination  IP address
 *
 * Asks the FW to open a TCP connection
 */
static int beiscsi_open_conn(struct iscsi_endpoint *ep,
			     struct sockaddr *src_addr,
			     struct sockaddr *dst_addr, int non_blocking)
{
	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
	struct beiscsi_hba *phba = beiscsi_ep->phba;
	struct be_queue_info *mccq = &phba->ctrl.mcc_obj.q;
	struct be_mcc_wrb *wrb;
	struct tcp_connect_and_offload_out *ptcpcnct_out;
	unsigned short status, extd_status;
	struct be_dma_mem nonemb_cmd;
	unsigned int tag, wrb_num;
	int ret = -ENOMEM;

	SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn\n");
	beiscsi_ep->ep_cid = beiscsi_get_cid(phba);
	if (beiscsi_ep->ep_cid == 0xFFFF) {
		SE_DEBUG(DBG_LVL_1, "No free cid available\n");
		return ret;
	}
	SE_DEBUG(DBG_LVL_8, "In beiscsi_open_conn, ep_cid=%d\n",
		 beiscsi_ep->ep_cid);
	phba->ep_array[beiscsi_ep->ep_cid -
		       phba->fw_config.iscsi_cid_start] = ep;
	if (beiscsi_ep->ep_cid > (phba->fw_config.iscsi_cid_start +
				  phba->params.cxns_per_ctrl * 2)) {
		SE_DEBUG(DBG_LVL_1, "Failed in allocate iscsi cid\n");
		goto free_ep;
	}

	beiscsi_ep->cid_vld = 0;
	nonemb_cmd.va = pci_alloc_consistent(phba->ctrl.pdev,
				sizeof(struct tcp_connect_and_offload_in),
				&nonemb_cmd.dma);
	if (nonemb_cmd.va == NULL) {
		SE_DEBUG(DBG_LVL_1,
			 "Failed to allocate memory for mgmt_open_connection"
			 "\n");
		beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
		return -ENOMEM;
	}
	nonemb_cmd.size = sizeof(struct tcp_connect_and_offload_in);
	memset(nonemb_cmd.va, 0, nonemb_cmd.size);
	tag = mgmt_open_connection(phba, dst_addr, beiscsi_ep, &nonemb_cmd);
	if (!tag) {
		SE_DEBUG(DBG_LVL_1,
			 "mgmt_open_connection Failed for cid=%d\n",
			 beiscsi_ep->ep_cid);
		beiscsi_put_cid(phba, beiscsi_ep->ep_cid);
		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
				    nonemb_cmd.va, nonemb_cmd.dma);
		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, "mgmt_open_connection Failed"
				    " status = %d extd_status = %d\n",
				    status, extd_status);
		free_mcc_tag(&phba->ctrl, tag);
		pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
			    nonemb_cmd.va, nonemb_cmd.dma);
		goto free_ep;
	} else {
		wrb = queue_get_wrb(mccq, wrb_num);
		free_mcc_tag(&phba->ctrl, tag);

		ptcpcnct_out = embedded_payload(wrb);
		beiscsi_ep = ep->dd_data;
		beiscsi_ep->fw_handle = ptcpcnct_out->connection_handle;
		beiscsi_ep->cid_vld = 1;
		SE_DEBUG(DBG_LVL_8, "mgmt_open_connection Success\n");
	}
	pci_free_consistent(phba->ctrl.pdev, nonemb_cmd.size,
			    nonemb_cmd.va, nonemb_cmd.dma);
	return 0;

free_ep:
	beiscsi_free_ep(beiscsi_ep);
	return -EBUSY;
}