}
}
-void qedf_update_src_mac(struct fc_lport *lport, u8 *addr)
-{
- struct qedf_ctx *qedf = lport_priv(lport);
-
- QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
- "Setting data_src_addr=%pM.\n", addr);
- ether_addr_copy(qedf->data_src_addr, addr);
-}
-
u8 *qedf_get_src_mac(struct fc_lport *lport)
{
- u8 mac[ETH_ALEN];
- u8 port_id[3];
struct qedf_ctx *qedf = lport_priv(lport);
- /* We need to use the lport port_id to create the data_src_addr */
- if (is_zero_ether_addr(qedf->data_src_addr)) {
- hton24(port_id, lport->port_id);
- fc_fcoe_set_mac(mac, port_id);
- qedf->ctlr.update_mac(lport, mac);
- }
return qedf->data_src_addr;
}
#include <linux/kthread.h>
#include <scsi/libfc.h>
#include <scsi/scsi_host.h>
+#include <scsi/fc_frame.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <linux/cpu.h>
}
}
+#define QEDF_FCOE_MAC_METHOD_GRANGED_MAC 1
+#define QEDF_FCOE_MAC_METHOD_FCF_MAP 2
+#define QEDF_FCOE_MAC_METHOD_FCOE_SET_MAC 3
+static void qedf_set_data_src_addr(struct qedf_ctx *qedf, struct fc_frame *fp)
+{
+ u8 *granted_mac;
+ struct fc_frame_header *fh = fc_frame_header_get(fp);
+ u8 fc_map[3];
+ int method = 0;
+
+ /* Get granted MAC address from FIP FLOGI payload */
+ granted_mac = fr_cb(fp)->granted_mac;
+
+ /*
+ * We set the source MAC for FCoE traffic based on the Granted MAC
+ * address from the switch.
+ *
+ * If granted_mac is non-zero, we used that.
+ * If the granted_mac is zeroed out, created the FCoE MAC based on
+ * the sel_fcf->fc_map and the d_id fo the FLOGI frame.
+ * If sel_fcf->fc_map is 0 then we use the default FCF-MAC plus the
+ * d_id of the FLOGI frame.
+ */
+ if (!is_zero_ether_addr(granted_mac)) {
+ ether_addr_copy(qedf->data_src_addr, granted_mac);
+ method = QEDF_FCOE_MAC_METHOD_GRANGED_MAC;
+ } else if (qedf->ctlr.sel_fcf->fc_map != 0) {
+ hton24(fc_map, qedf->ctlr.sel_fcf->fc_map);
+ qedf->data_src_addr[0] = fc_map[0];
+ qedf->data_src_addr[1] = fc_map[1];
+ qedf->data_src_addr[2] = fc_map[2];
+ qedf->data_src_addr[3] = fh->fh_d_id[0];
+ qedf->data_src_addr[4] = fh->fh_d_id[1];
+ qedf->data_src_addr[5] = fh->fh_d_id[2];
+ method = QEDF_FCOE_MAC_METHOD_FCF_MAP;
+ } else {
+ fc_fcoe_set_mac(qedf->data_src_addr, fh->fh_d_id);
+ method = QEDF_FCOE_MAC_METHOD_FCOE_SET_MAC;
+ }
+
+ QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
+ "QEDF data_src_mac=%pM method=%d.\n", qedf->data_src_addr, method);
+}
+
static void qedf_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
void *arg)
{
/* Log stats for FLOGI reject */
if (fc_frame_payload_op(fp) == ELS_LS_RJT)
qedf->flogi_failed++;
+ else if (fc_frame_payload_op(fp) == ELS_LS_ACC) {
+ /* Set the source MAC we will use for FCoE traffic */
+ qedf_set_data_src_addr(qedf, fp);
+ }
/* Complete flogi_compl so we can proceed to sending ADISCs */
complete(&qedf->flogi_compl);
ether_addr_copy(eh->h_dest, qedf->ctlr.dest_addr);
/* Set the source MAC address */
- fc_fcoe_set_mac(eh->h_source, fh->fh_s_id);
+ ether_addr_copy(eh->h_source, qedf->data_src_addr);
hp = (struct fcoe_hdr *)(eh + 1);
memset(hp, 0, sizeof(*hp));
{
struct qed_fcoe_params_offload conn_info;
u32 port_id;
- u8 lport_src_id[3];
int rval;
uint16_t total_sqe = (fcport->sq_mem_size / sizeof(struct fcoe_wqe));
(dma_addr_t)(*(u64 *)(fcport->sq_pbl + 8));
/* Need to use our FCoE MAC for the offload session */
- port_id = fc_host_port_id(qedf->lport->host);
- lport_src_id[2] = (port_id & 0x000000FF);
- lport_src_id[1] = (port_id & 0x0000FF00) >> 8;
- lport_src_id[0] = (port_id & 0x00FF0000) >> 16;
- fc_fcoe_set_mac(conn_info.src_mac, lport_src_id);
+ ether_addr_copy(conn_info.src_mac, qedf->data_src_addr);
ether_addr_copy(conn_info.dst_mac, qedf->ctlr.dest_addr);
fcoe_ctlr_init(&qedf->ctlr, FIP_ST_AUTO);
qedf->ctlr.send = qedf_fip_send;
- qedf->ctlr.update_mac = qedf_update_src_mac;
qedf->ctlr.get_src_addr = qedf_get_src_mac;
ether_addr_copy(qedf->ctlr.ctl_src_addr, qedf->mac);
}