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); }
/* * Check the CRC in a frame. */ u32 fc_frame_crc_check(struct fc_frame *fp) { u32 crc; u32 error; const u8 *bp; unsigned int len; WARN_ON(!fc_frame_is_linear(fp)); fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED; len = (fr_len(fp) + 3) & ~3; /* round up length to include fill */ bp = (const u8 *) fr_hdr(fp); crc = ~crc32(~0, bp, len); error = crc ^ fr_crc(fp); return error; }