nfp: nsp: add support for optional hwinfo lookup
authorDirk van der Merwe <dirk.vandermerwe@netronome.com>
Sun, 8 Sep 2019 23:54:20 +0000 (00:54 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 10 Sep 2019 16:29:26 +0000 (17:29 +0100)
There are cases where we want to read a hwinfo entry from the NFP, and
if it doesn't exist, use a default value instead.

To support this, we must silence warning/error messages when the hwinfo
entry doesn't exist since this is a valid use case. The NSP command
structure provides the ability to silence command errors, in which case
the caller should log any command errors appropriately. Protocol errors
are unaffected by this.

Signed-off-by: Dirk van der Merwe <dirk.vandermerwe@netronome.com>
Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.c
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp.h

index b4c5dc5f7404c237d0195134ff7817c7c7a785e5..deee91cbf1b250900e74f82ddd27ef900526b046 100644 (file)
@@ -144,6 +144,8 @@ struct nfp_nsp {
  * @option:    NFP SP Command Argument
  * @buf:       NFP SP Buffer Address
  * @error_cb:  Callback for interpreting option if error occurred
+ * @error_quiet:Don't print command error/warning. Protocol errors are still
+ *                 logged.
  */
 struct nfp_nsp_command_arg {
        u16 code;
@@ -152,6 +154,7 @@ struct nfp_nsp_command_arg {
        u32 option;
        u64 buf;
        void (*error_cb)(struct nfp_nsp *state, u32 ret_val);
+       bool error_quiet;
 };
 
 /**
@@ -406,8 +409,10 @@ __nfp_nsp_command(struct nfp_nsp *state, const struct nfp_nsp_command_arg *arg)
 
        err = FIELD_GET(NSP_STATUS_RESULT, reg);
        if (err) {
-               nfp_warn(cpp, "Result (error) code set: %d (%d) command: %d\n",
-                        -err, (int)ret_val, arg->code);
+               if (!arg->error_quiet)
+                       nfp_warn(cpp, "Result (error) code set: %d (%d) command: %d\n",
+                                -err, (int)ret_val, arg->code);
+
                if (arg->error_cb)
                        arg->error_cb(state, ret_val);
                else
@@ -892,12 +897,14 @@ int nfp_nsp_load_stored_fw(struct nfp_nsp *state)
 }
 
 static int
-__nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size)
+__nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size,
+                       bool optional)
 {
        struct nfp_nsp_command_buf_arg hwinfo_lookup = {
                {
                        .code           = SPCODE_HWINFO_LOOKUP,
                        .option         = size,
+                       .error_quiet    = optional,
                },
                .in_buf         = buf,
                .in_size        = size,
@@ -914,7 +921,7 @@ int nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size)
 
        size = min_t(u32, size, NFP_HWINFO_LOOKUP_SIZE);
 
-       err = __nfp_nsp_hwinfo_lookup(state, buf, size);
+       err = __nfp_nsp_hwinfo_lookup(state, buf, size, false);
        if (err)
                return err;
 
@@ -926,6 +933,43 @@ int nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size)
        return 0;
 }
 
+int nfp_nsp_hwinfo_lookup_optional(struct nfp_nsp *state, void *buf,
+                                  unsigned int size, const char *default_val)
+{
+       int err;
+
+       /* Ensure that the default value is usable irrespective of whether
+        * it is actually going to be used.
+        */
+       if (strnlen(default_val, size) == size)
+               return -EINVAL;
+
+       if (!nfp_nsp_has_hwinfo_lookup(state)) {
+               strcpy(buf, default_val);
+               return 0;
+       }
+
+       size = min_t(u32, size, NFP_HWINFO_LOOKUP_SIZE);
+
+       err = __nfp_nsp_hwinfo_lookup(state, buf, size, true);
+       if (err) {
+               if (err == -ENOENT) {
+                       strcpy(buf, default_val);
+                       return 0;
+               }
+
+               nfp_err(state->cpp, "NSP HWinfo lookup failed: %d\n", err);
+               return err;
+       }
+
+       if (strnlen(buf, size) == size) {
+               nfp_err(state->cpp, "NSP HWinfo value not NULL-terminated\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 int nfp_nsp_fw_loaded(struct nfp_nsp *state)
 {
        const struct nfp_nsp_command_arg arg = {
index 4ceecff347c6ceb35855bd95bc53f287a11d4d10..a8985c2eb1f11b01b21cec9c84c374c1651d110d 100644 (file)
@@ -22,6 +22,8 @@ int nfp_nsp_write_flash(struct nfp_nsp *state, const struct firmware *fw);
 int nfp_nsp_mac_reinit(struct nfp_nsp *state);
 int nfp_nsp_load_stored_fw(struct nfp_nsp *state);
 int nfp_nsp_hwinfo_lookup(struct nfp_nsp *state, void *buf, unsigned int size);
+int nfp_nsp_hwinfo_lookup_optional(struct nfp_nsp *state, void *buf,
+                                  unsigned int size, const char *default_val);
 int nfp_nsp_fw_loaded(struct nfp_nsp *state);
 int nfp_nsp_read_module_eeprom(struct nfp_nsp *state, int eth_index,
                               unsigned int offset, void *data,