qed: Add support for changing iSCSI mac
authorMintz, Yuval <Yuval.Mintz@cavium.com>
Fri, 2 Jun 2017 05:58:33 +0000 (08:58 +0300)
committerDavid S. Miller <davem@davemloft.net>
Fri, 2 Jun 2017 14:33:03 +0000 (10:33 -0400)
Enhance API between qedi and qed, allowing qedi to inform device's
firmware when the iSCSI mac is to be changed.

Signed-off-by: Yuval Mintz <Yuval.Mintz@cavium.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/qlogic/qed/qed_iscsi.c
drivers/net/ethernet/qlogic/qed/qed_sp.h
include/linux/qed/qed_iscsi_if.h

index bc8ce09d390f07347d2b1e406639266f50edc5b6..6103723d71180022ed3849cb7313f1fef5b8c753 100644 (file)
@@ -488,6 +488,54 @@ static int qed_sp_iscsi_conn_update(struct qed_hwfn *p_hwfn,
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
 
+static int
+qed_sp_iscsi_mac_update(struct qed_hwfn *p_hwfn,
+                       struct qed_iscsi_conn *p_conn,
+                       enum spq_mode comp_mode,
+                       struct qed_spq_comp_cb *p_comp_addr)
+{
+       struct iscsi_spe_conn_mac_update *p_ramrod = NULL;
+       struct qed_spq_entry *p_ent = NULL;
+       struct qed_sp_init_data init_data;
+       int rc = -EINVAL;
+       u8 ucval;
+
+       /* Get SPQ entry */
+       memset(&init_data, 0, sizeof(init_data));
+       init_data.cid = p_conn->icid;
+       init_data.opaque_fid = p_hwfn->hw_info.opaque_fid;
+       init_data.comp_mode = comp_mode;
+       init_data.p_comp_data = p_comp_addr;
+
+       rc = qed_sp_init_request(p_hwfn, &p_ent,
+                                ISCSI_RAMROD_CMD_ID_MAC_UPDATE,
+                                PROTOCOLID_ISCSI, &init_data);
+       if (rc)
+               return rc;
+
+       p_ramrod = &p_ent->ramrod.iscsi_conn_mac_update;
+       p_ramrod->hdr.op_code = ISCSI_RAMROD_CMD_ID_MAC_UPDATE;
+       SET_FIELD(p_ramrod->hdr.flags,
+                 ISCSI_SLOW_PATH_HDR_LAYER_CODE, p_conn->layer_code);
+
+       p_ramrod->conn_id = cpu_to_le16(p_conn->conn_id);
+       p_ramrod->fw_cid = cpu_to_le32(p_conn->icid);
+       ucval = p_conn->remote_mac[1];
+       ((u8 *)(&p_ramrod->remote_mac_addr_hi))[0] = ucval;
+       ucval = p_conn->remote_mac[0];
+       ((u8 *)(&p_ramrod->remote_mac_addr_hi))[1] = ucval;
+       ucval = p_conn->remote_mac[3];
+       ((u8 *)(&p_ramrod->remote_mac_addr_mid))[0] = ucval;
+       ucval = p_conn->remote_mac[2];
+       ((u8 *)(&p_ramrod->remote_mac_addr_mid))[1] = ucval;
+       ucval = p_conn->remote_mac[5];
+       ((u8 *)(&p_ramrod->remote_mac_addr_lo))[0] = ucval;
+       ucval = p_conn->remote_mac[4];
+       ((u8 *)(&p_ramrod->remote_mac_addr_lo))[1] = ucval;
+
+       return qed_spq_post(p_hwfn, p_ent, NULL);
+}
+
 static int qed_sp_iscsi_conn_terminate(struct qed_hwfn *p_hwfn,
                                       struct qed_iscsi_conn *p_conn,
                                       enum spq_mode comp_mode,
@@ -1324,6 +1372,23 @@ static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats)
        return qed_iscsi_get_stats(QED_LEADING_HWFN(cdev), stats);
 }
 
+static int qed_iscsi_change_mac(struct qed_dev *cdev,
+                               u32 handle, const u8 *mac)
+{
+       struct qed_hash_iscsi_con *hash_con;
+
+       hash_con = qed_iscsi_get_hash(cdev, handle);
+       if (!hash_con) {
+               DP_NOTICE(cdev, "Failed to find connection for handle %d\n",
+                         handle);
+               return -EINVAL;
+       }
+
+       return qed_sp_iscsi_mac_update(QED_LEADING_HWFN(cdev),
+                                      hash_con->con,
+                                      QED_SPQ_MODE_EBLOCK, NULL);
+}
+
 void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
                                  struct qed_mcp_iscsi_stats *stats)
 {
@@ -1358,6 +1423,7 @@ static const struct qed_iscsi_ops qed_iscsi_ops_pass = {
        .destroy_conn = &qed_iscsi_destroy_conn,
        .clear_sq = &qed_iscsi_clear_conn_sq,
        .get_stats = &qed_iscsi_stats,
+       .change_mac = &qed_iscsi_change_mac,
 };
 
 const struct qed_iscsi_ops *qed_get_iscsi_ops(void)
index b9464f3ab0e23eee75cfcf606c78b0f90c5b0a1f..00dd50f8c42fed71e5778c68e5240399ced4b362 100644 (file)
@@ -120,6 +120,7 @@ union ramrod_data {
        struct iscsi_spe_func_dstry iscsi_destroy;
        struct iscsi_spe_conn_offload iscsi_conn_offload;
        struct iscsi_conn_update_ramrod_params iscsi_conn_update;
+       struct iscsi_spe_conn_mac_update iscsi_conn_mac_update;
        struct iscsi_spe_conn_termination iscsi_conn_terminate;
 
        struct vf_start_ramrod_data vf_start;
index 3414649133d2e44fe36b9c12e12f42ba6970ed9d..111e606a74c88ad6fb221cdcfc8f8c584c5cd765 100644 (file)
@@ -210,6 +210,11 @@ struct qed_iscsi_cb_ops {
  *                     @param stats - pointer to struck that would be filled
  *                             we stats
  *                     @return 0 on success, error otherwise.
+ * @change_mac         Change MAC of interface
+ *                     @param cdev
+ *                     @param handle - the connection handle.
+ *                     @param mac - new MAC to configure.
+ *                     @return 0 on success, otherwise error value.
  */
 struct qed_iscsi_ops {
        const struct qed_common_ops *common;
@@ -248,6 +253,8 @@ struct qed_iscsi_ops {
 
        int (*get_stats)(struct qed_dev *cdev,
                         struct qed_iscsi_stats *stats);
+
+       int (*change_mac)(struct qed_dev *cdev, u32 handle, const u8 *mac);
 };
 
 const struct qed_iscsi_ops *qed_get_iscsi_ops(void);