示例#1
0
void
iscsi_iser_recv(struct iscsi_conn *conn,
		struct iscsi_hdr *hdr, char *rx_data, int rx_data_len)
{
	int rc = 0;
	int datalen;
	int ahslen;

	/* verify PDU length */
	datalen = ntoh24(hdr->dlength);
	if (datalen != rx_data_len) {
		printk(KERN_ERR "iscsi_iser: datalen %d (hdr) != %d (IB) \n",
		       datalen, rx_data_len);
		rc = ISCSI_ERR_DATALEN;
		goto error;
	}

	/* read AHS */
	ahslen = hdr->hlength * 4;

	rc = iscsi2_complete_pdu(conn, hdr, rx_data, rx_data_len);
	if (rc && rc != ISCSI_ERR_NO_SCSI_CMD)
		goto error;

	return;
error:
	iscsi2_conn_failure(conn, rc);
}
示例#2
0
static void iser_handle_comp_error(struct iser_desc *desc)
{
	struct iser_dto  *dto     = &desc->dto;
	struct iser_conn *ib_conn = dto->ib_conn;

	iser_dto_buffs_release(dto);

	if (desc->type == ISCSI_RX) {
		kfree(desc->data);
		kmem_cache_free(ig.desc_cache, desc);
		atomic_dec(&ib_conn->post_recv_buf_count);
	} else { /* type is TX control/command/dataout */
		if (desc->type == ISCSI_TX_DATAOUT)
			kmem_cache_free(ig.desc_cache, desc);
		atomic_dec(&ib_conn->post_send_buf_count);
	}

	if (atomic_read(&ib_conn->post_recv_buf_count) == 0 &&
	    atomic_read(&ib_conn->post_send_buf_count) == 0) {
		/* getting here when the state is UP means that the conn is *
		 * being terminated asynchronously from the iSCSI layer's   *
		 * perspective.                                             */
		if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
		    ISER_CONN_TERMINATING))
			iscsi2_conn_failure(ib_conn->iser_conn->iscsi_conn,
					   ISCSI_ERR_CONN_FAILED);

		/* complete the termination process if disconnect event was delivered *
		 * note there are no more non completed posts to the QP               */
		if (ib_conn->disc_evt_flag) {
			ib_conn->state = ISER_CONN_DOWN;
			wake_up_interruptible(&ib_conn->wait);
		}
	}
}
示例#3
0
void cxgb3i_conn_closing(struct s3_conn *c3cn)
{
	struct iscsi_conn *conn;

	read_lock(&c3cn->callback_lock);
	conn = c3cn->user_data;
	if (conn && c3cn->state != C3CN_STATE_ESTABLISHED)
		iscsi2_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
	read_unlock(&c3cn->callback_lock);
}
示例#4
0
int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
{
	struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
	struct cxgb3i_conn *cconn = tcp_conn->dd_data;
	struct iscsi_tcp_task *tcp_task = task->dd_data;
	struct cxgb3i_task_data *tdata = tcp_task->dd_data;
	struct sk_buff *skb = tdata->skb;
	unsigned int datalen;
	int err;

	if (!skb)
		return 0;

	datalen = skb->data_len;
	tdata->skb = NULL;
	err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb);
	if (err > 0) {
		int pdulen = err;

	cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
			task, skb, skb->len, skb->data_len, err);

		if (task->conn->hdrdgst_en)
			pdulen += ISCSI_DIGEST_SIZE;
		if (datalen && task->conn->datadgst_en)
			pdulen += ISCSI_DIGEST_SIZE;

		task->conn->txdata_octets += pdulen;
		return 0;
	}

	if (err == -EAGAIN || err == -ENOBUFS) {
		/* reset skb to send when we are called again */
		tdata->skb = skb;
		return err;
	}

	kfree_skb(skb);
	cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
			task->itt, skb, skb->len, skb->data_len, err);
	iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
	iscsi2_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
	return err;
}
示例#5
0
static void iser_disconnected_handler(struct rdma_cm_id *cma_id)
{
	struct iser_conn *ib_conn;

	ib_conn = (struct iser_conn *)cma_id->context;
	ib_conn->disc_evt_flag = 1;

	/* getting here when the state is UP means that the conn is being *
	 * terminated asynchronously from the iSCSI layer's perspective.  */
	if (iser_conn_state_comp_exch(ib_conn, ISER_CONN_UP,
				      ISER_CONN_TERMINATING))
		iscsi2_conn_failure(ib_conn->iser_conn->iscsi_conn,
				   ISCSI_ERR_CONN_FAILED);

	/* Complete the termination process if no posts are pending */
	if ((atomic_read(&ib_conn->post_recv_buf_count) == 0) &&
	    (atomic_read(&ib_conn->post_send_buf_count) == 0)) {
		ib_conn->state = ISER_CONN_DOWN;
		wake_up_interruptible(&ib_conn->wait);
	}
}
示例#6
0
void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn)
{
	struct sk_buff *skb;
	unsigned int read = 0;
	struct iscsi_conn *conn = c3cn->user_data;
	int err = 0;

	cxgb3i_rx_debug("cn 0x%p.\n", c3cn);

	read_lock(&c3cn->callback_lock);
	if (unlikely(!conn || conn->suspend_rx)) {
		cxgb3i_rx_debug("conn 0x%p, id %d, suspend_rx %lu!\n",
				conn, conn ? conn->id : 0xFF,
				conn ? conn->suspend_rx : 0xFF);
		read_unlock(&c3cn->callback_lock);
		return;
	}
	skb = skb_peek(&c3cn->receive_queue);
	while (!err && skb) {
		__skb_unlink(skb, &c3cn->receive_queue);
		read += skb_rx_pdulen(skb);
		cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n",
				conn, c3cn, skb, skb_rx_pdulen(skb));
		err = cxgb3i_conn_read_pdu_skb(conn, skb);
		__kfree_skb(skb);
		skb = skb_peek(&c3cn->receive_queue);
	}
	read_unlock(&c3cn->callback_lock);
	if (c3cn) {
		c3cn->copied_seq += read;
		cxgb3i_c3cn_rx_credits(c3cn, read);
	}
	conn->rxdata_octets += read;

	if (err) {
		cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err);
		iscsi2_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
	}
}
示例#7
0
static int cxgb3i_conn_read_pdu_skb(struct iscsi_conn *conn,
				    struct sk_buff *skb)
{
	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
	bool offloaded = 0;
	unsigned int offset;
	int rc;

	cxgb3i_rx_debug("conn 0x%p, skb 0x%p, len %u, flag 0x%x.\n",
			conn, skb, skb->len, skb_ulp_mode(skb));

	if (!iscsi_tcp_recv_segment_is_hdr(tcp_conn)) {
		iscsi2_conn_failure(conn, ISCSI_ERR_PROTO);
		return -EIO;
	}

	if (conn->hdrdgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_HCRC_ERROR)) {
		iscsi2_conn_failure(conn, ISCSI_ERR_HDR_DGST);
		return -EIO;
	}

	if (conn->datadgst_en && (skb_ulp_mode(skb) & ULP2_FLAG_DCRC_ERROR)) {
		iscsi2_conn_failure(conn, ISCSI_ERR_DATA_DGST);
		return -EIO;
	}

	/* iscsi hdr */
	rc = read_pdu_skb(conn, skb, 0, 0);
	if (rc <= 0)
		return rc;

	if (iscsi_tcp_recv_segment_is_hdr(tcp_conn))
		return 0;

	offset = rc;
	if (conn->hdrdgst_en)
		offset += ISCSI_DIGEST_SIZE;

	/* iscsi data */
	if (skb_ulp_mode(skb) & ULP2_FLAG_DATA_DDPED) {
		cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, ddp'ed, "
				"itt 0x%x.\n",
				skb,
				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
				tcp_conn->in.datalen,
				ntohl(tcp_conn->in.hdr->itt));
		offloaded = 1;
	} else {
		cxgb3i_rx_debug("skb 0x%p, opcode 0x%x, data %u, NOT ddp'ed, "
				"itt 0x%x.\n",
				skb,
				tcp_conn->in.hdr->opcode & ISCSI_OPCODE_MASK,
				tcp_conn->in.datalen,
				ntohl(tcp_conn->in.hdr->itt));
		offset += sizeof(struct cpl_iscsi_hdr_norss);
	}

	rc = read_pdu_skb(conn, skb, offset, offloaded);
	if (rc < 0)
		return rc;
	else
		return 0;
}