Пример #1
0
static void qedf_process_l2_frame_compl(struct qedf_rport *fcport,
					struct fc_frame *fp,
					u16 l2_oxid)
{
	struct fc_lport *lport = fcport->qedf->lport;
	struct fc_frame_header *fh;
	u32 crc;

	fh = (struct fc_frame_header *)fc_frame_header_get(fp);

	/* Set the OXID we return to what libfc used */
	if (l2_oxid != FC_XID_UNKNOWN)
		fh->fh_ox_id = htons(l2_oxid);

	/* Setup header fields */
	fh->fh_r_ctl = FC_RCTL_ELS_REP;
	fh->fh_type = FC_TYPE_ELS;
	/* Last sequence, end sequence */
	fh->fh_f_ctl[0] = 0x98;
	hton24(fh->fh_d_id, lport->port_id);
	hton24(fh->fh_s_id, fcport->rdata->ids.port_id);
	fh->fh_rx_id = 0xffff;

	/* Set frame attributes */
	crc = fcoe_fc_crc(fp);
	fc_frame_init(fp);
	fr_dev(fp) = lport;
	fr_sof(fp) = FC_SOF_I3;
	fr_eof(fp) = FC_EOF_T;
	fr_crc(fp) = cpu_to_le32(~crc);

	/* Send completed request to libfc */
	fc_exch_recv(lport, fp);
}
Пример #2
0
static void ft_free_cmd(struct ft_cmd *cmd)
{
	struct fc_frame *fp;
	struct fc_lport *lport;

	if (!cmd)
		return;
	fp = cmd->req_frame;
	lport = fr_dev(fp);
	if (fr_seq(fp))
		lport->tt.seq_release(fr_seq(fp));
	fc_frame_free(fp);
	ft_sess_put(cmd->sess);	/* undo get from lookup at recv */
	kfree(cmd);
}
Пример #3
0
static void ft_free_cmd(struct ft_cmd *cmd)
{
	struct fc_frame *fp;
	struct fc_lport *lport;
	struct ft_sess *sess;

	if (!cmd)
		return;
	sess = cmd->sess;
	fp = cmd->req_frame;
	lport = fr_dev(fp);
	if (fr_seq(fp))
		lport->tt.seq_release(fr_seq(fp));
	fc_frame_free(fp);
	percpu_ida_free(&sess->se_sess->sess_tag_pool, cmd->se_cmd.map_tag);
	ft_sess_put(sess);	/* undo get from lookup at recv */
}
Пример #4
0
static void fnic_rq_cmpl_frame_recv(struct vnic_rq *rq, struct cq_desc
				    *cq_desc, struct vnic_rq_buf *buf,
				    int skipped __attribute__((unused)),
				    void *opaque)
{
	struct fnic *fnic = vnic_dev_priv(rq->vdev);
	struct sk_buff *skb;
	struct fc_frame *fp;
	unsigned int eth_hdrs_stripped;
	u8 type, color, eop, sop, ingress_port, vlan_stripped;
	u8 fcoe = 0, fcoe_sof, fcoe_eof;
	u8 fcoe_fc_crc_ok = 1, fcoe_enc_error = 0;
	u8 tcp_udp_csum_ok, udp, tcp, ipv4_csum_ok;
	u8 ipv6, ipv4, ipv4_fragment, rss_type, csum_not_calc;
	u8 fcs_ok = 1, packet_error = 0;
	u16 q_number, completed_index, bytes_written = 0, vlan, checksum;
	u32 rss_hash;
	u16 exchange_id, tmpl;
	u8 sof = 0;
	u8 eof = 0;
	u32 fcp_bytes_written = 0;
	unsigned long flags;

	pci_unmap_single(fnic->pdev, buf->dma_addr, buf->len,
			 PCI_DMA_FROMDEVICE);
	skb = buf->os_buf;
	buf->os_buf = NULL;

	cq_desc_dec(cq_desc, &type, &color, &q_number, &completed_index);
	if (type == CQ_DESC_TYPE_RQ_FCP) {
		cq_fcp_rq_desc_dec((struct cq_fcp_rq_desc *)cq_desc,
				   &type, &color, &q_number, &completed_index,
				   &eop, &sop, &fcoe_fc_crc_ok, &exchange_id,
				   &tmpl, &fcp_bytes_written, &sof, &eof,
				   &ingress_port, &packet_error,
				   &fcoe_enc_error, &fcs_ok, &vlan_stripped,
				   &vlan);
		eth_hdrs_stripped = 1;

	} else if (type == CQ_DESC_TYPE_RQ_ENET) {
		cq_enet_rq_desc_dec((struct cq_enet_rq_desc *)cq_desc,
				    &type, &color, &q_number, &completed_index,
				    &ingress_port, &fcoe, &eop, &sop,
				    &rss_type, &csum_not_calc, &rss_hash,
				    &bytes_written, &packet_error,
				    &vlan_stripped, &vlan, &checksum,
				    &fcoe_sof, &fcoe_fc_crc_ok,
				    &fcoe_enc_error, &fcoe_eof,
				    &tcp_udp_csum_ok, &udp, &tcp,
				    &ipv4_csum_ok, &ipv6, &ipv4,
				    &ipv4_fragment, &fcs_ok);
		eth_hdrs_stripped = 0;

	} else {
		/* wrong CQ type*/
		shost_printk(KERN_ERR, fnic->lport->host,
			     "fnic rq_cmpl wrong cq type x%x\n", type);
		goto drop;
	}

	if (!fcs_ok || packet_error || !fcoe_fc_crc_ok || fcoe_enc_error) {
		FNIC_FCS_DBG(KERN_DEBUG, fnic->lport->host,
			     "fnic rq_cmpl fcoe x%x fcsok x%x"
			     " pkterr x%x fcoe_fc_crc_ok x%x, fcoe_enc_err"
			     " x%x\n",
			     fcoe, fcs_ok, packet_error,
			     fcoe_fc_crc_ok, fcoe_enc_error);
		goto drop;
	}

	if (eth_hdrs_stripped)
		fnic_import_rq_fc_frame(skb, fcp_bytes_written, sof, eof);
	else if (fnic_import_rq_eth_pkt(skb, bytes_written))
		goto drop;

	fp = (struct fc_frame *)skb;

	/*
	 * If frame is an ELS response that matches the cached FLOGI OX_ID,
	 * and is accept, issue flogi_reg_request copy wq request to firmware
	 * to register the S_ID and determine whether FC_OUI mode or GW mode.
	 */
	if (is_matching_flogi_resp_frame(fnic, fp)) {
		if (!eth_hdrs_stripped) {
			if (fc_frame_payload_op(fp) == ELS_LS_ACC) {
				fnic_handle_flogi_resp(fnic, fp);
				return;
			}
			/*
			 * Recd. Flogi reject. No point registering
			 * with fw, but forward to libFC
			 */
			goto forward;
		}
		goto drop;
	}
	if (!eth_hdrs_stripped)
		goto drop;

forward:
	spin_lock_irqsave(&fnic->fnic_lock, flags);
	if (fnic->stop_rx_link_events) {
		spin_unlock_irqrestore(&fnic->fnic_lock, flags);
		goto drop;
	}
	/* Use fr_flags to indicate whether succ. flogi resp or not */
	fr_flags(fp) = 0;
	fr_dev(fp) = fnic->lport;
	spin_unlock_irqrestore(&fnic->fnic_lock, flags);

	skb_queue_tail(&fnic->frame_queue, skb);
	queue_work(fnic_event_queue, &fnic->frame_work);

	return;
drop:
	dev_kfree_skb_irq(skb);
}