ice: send driver version to firmware
authorPaul M Stillwell Jr <paul.m.stillwell.jr@intel.com>
Mon, 9 Sep 2019 13:47:42 +0000 (06:47 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Thu, 12 Sep 2019 17:22:04 +0000 (10:22 -0700)
The driver is required to send a version to the firmware
to indicate that the driver is up. If the driver doesn't
do this the firmware doesn't behave properly.

Signed-off-by: Paul M Stillwell Jr <paul.m.stillwell.jr@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
drivers/net/ethernet/intel/ice/ice_common.c
drivers/net/ethernet/intel/ice/ice_common.h
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_type.h

index b36e1cf0e461d573fee7941b7dca688faf7d9012..4cdedcebb163949258da0cfb21e63fe908ea9eb8 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/sctp.h>
 #include <linux/ipv6.h>
 #include <linux/if_bridge.h>
+#include <linux/ctype.h>
 #include <linux/avf/virtchnl.h>
 #include <net/ipv6.h>
 #include "ice_devids.h"
index 4da0cde9695bf871b222a12a4b938fa90ca879c3..9c9791788610708c1973bd9e67e47f4271e46c13 100644 (file)
@@ -33,6 +33,17 @@ struct ice_aqc_get_ver {
        u8 api_patch;
 };
 
+/* Send driver version (indirect 0x0002) */
+struct ice_aqc_driver_ver {
+       u8 major_ver;
+       u8 minor_ver;
+       u8 build_ver;
+       u8 subbuild_ver;
+       u8 reserved[4];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
 /* Queue Shutdown (direct 0x0003) */
 struct ice_aqc_q_shutdown {
        u8 driver_unloading;
@@ -1547,6 +1558,7 @@ struct ice_aq_desc {
                u8 raw[16];
                struct ice_aqc_generic generic;
                struct ice_aqc_get_ver get_ver;
+               struct ice_aqc_driver_ver driver_ver;
                struct ice_aqc_q_shutdown q_shutdown;
                struct ice_aqc_req_res res_owner;
                struct ice_aqc_manage_mac_read mac_read;
@@ -1618,6 +1630,7 @@ enum ice_aq_err {
 enum ice_adminq_opc {
        /* AQ commands */
        ice_aqc_opc_get_ver                             = 0x0001,
+       ice_aqc_opc_driver_ver                          = 0x0002,
        ice_aqc_opc_q_shutdown                          = 0x0003,
 
        /* resource ownership */
index 8b2c46615834f9ec302c82c5330db4227c032ef0..db62cc7485447ec26e66f476635300749ce24120 100644 (file)
@@ -1258,6 +1258,43 @@ enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd)
        return status;
 }
 
+/**
+ * ice_aq_send_driver_ver
+ * @hw: pointer to the HW struct
+ * @dv: driver's major, minor version
+ * @cd: pointer to command details structure or NULL
+ *
+ * Send the driver version (0x0002) to the firmware
+ */
+enum ice_status
+ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
+                      struct ice_sq_cd *cd)
+{
+       struct ice_aqc_driver_ver *cmd;
+       struct ice_aq_desc desc;
+       u16 len;
+
+       cmd = &desc.params.driver_ver;
+
+       if (!dv)
+               return ICE_ERR_PARAM;
+
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_driver_ver);
+
+       desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
+       cmd->major_ver = dv->major_ver;
+       cmd->minor_ver = dv->minor_ver;
+       cmd->build_ver = dv->build_ver;
+       cmd->subbuild_ver = dv->subbuild_ver;
+
+       len = 0;
+       while (len < sizeof(dv->driver_string) &&
+              isascii(dv->driver_string[len]) && dv->driver_string[len])
+               len++;
+
+       return ice_aq_send_cmd(hw, &desc, dv->driver_string, len, cd);
+}
+
 /**
  * ice_aq_q_shutdown
  * @hw: pointer to the HW struct
index e376d1eadba43d8f27a4f8ee05e9ea8bfa85704a..e9d77370a17c7377265e32410b0dfbf9daacdf6e 100644 (file)
@@ -71,6 +71,9 @@ ice_aq_send_cmd(struct ice_hw *hw, struct ice_aq_desc *desc,
                void *buf, u16 buf_size, struct ice_sq_cd *cd);
 enum ice_status ice_aq_get_fw_ver(struct ice_hw *hw, struct ice_sq_cd *cd);
 
+enum ice_status
+ice_aq_send_driver_ver(struct ice_hw *hw, struct ice_driver_ver *dv,
+                      struct ice_sq_cd *cd);
 enum ice_status
 ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
                    struct ice_aqc_get_phy_caps_data *caps,
index f8be9ada2447bdc44f887231f889c342c88aca3e..c0988b74f00738196d80a768f782e40577db4d83 100644 (file)
@@ -9,7 +9,13 @@
 #include "ice_lib.h"
 #include "ice_dcb_lib.h"
 
-#define DRV_VERSION    "0.7.5-k"
+#define DRV_VERSION_MAJOR 0
+#define DRV_VERSION_MINOR 7
+#define DRV_VERSION_BUILD 5
+
+#define DRV_VERSION    __stringify(DRV_VERSION_MAJOR) "." \
+                       __stringify(DRV_VERSION_MINOR) "." \
+                       __stringify(DRV_VERSION_BUILD) "-k"
 #define DRV_SUMMARY    "Intel(R) Ethernet Connection E800 Series Linux Driver"
 const char ice_drv_ver[] = DRV_VERSION;
 static const char ice_driver_string[] = DRV_SUMMARY;
@@ -2459,6 +2465,25 @@ static void ice_verify_cacheline_size(struct ice_pf *pf)
                         ICE_CACHE_LINE_BYTES);
 }
 
+/**
+ * ice_send_version - update firmware with driver version
+ * @pf: PF struct
+ *
+ * Returns ICE_SUCCESS on success, else error code
+ */
+static enum ice_status ice_send_version(struct ice_pf *pf)
+{
+       struct ice_driver_ver dv;
+
+       dv.major_ver = DRV_VERSION_MAJOR;
+       dv.minor_ver = DRV_VERSION_MINOR;
+       dv.build_ver = DRV_VERSION_BUILD;
+       dv.subbuild_ver = 0;
+       strscpy((char *)dv.driver_string, DRV_VERSION,
+               sizeof(dv.driver_string));
+       return ice_aq_send_driver_ver(&pf->hw, &dv, NULL);
+}
+
 /**
  * ice_probe - Device initialization routine
  * @pdev: PCI device information struct
@@ -2612,6 +2637,15 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
 
        clear_bit(__ICE_SERVICE_DIS, pf->state);
 
+       /* tell the firmware we are up */
+       err = ice_send_version(pf);
+       if (err) {
+               dev_err(dev,
+                       "probe failed sending driver version %s. error: %d\n",
+                       ice_drv_ver, err);
+               goto err_alloc_sw_unroll;
+       }
+
        /* since everything is good, start the service timer */
        mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period));
 
index 4501d50a7dcc6c70d703e8a7d86c059afde27eb7..a2676003275a2141a24d887a53c10659054423bc 100644 (file)
@@ -53,6 +53,14 @@ enum ice_aq_res_access_type {
        ICE_RES_WRITE
 };
 
+struct ice_driver_ver {
+       u8 major_ver;
+       u8 minor_ver;
+       u8 build_ver;
+       u8 subbuild_ver;
+       u8 driver_string[32];
+};
+
 enum ice_fc_mode {
        ICE_FC_NONE = 0,
        ICE_FC_RX_PAUSE,