root/drivers/block/rsxx/config.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. initialize_config
  2. config_data_crc32
  3. config_hdr_be_to_cpu
  4. config_hdr_cpu_to_be
  5. config_data_swab
  6. config_data_le_to_cpu
  7. config_data_cpu_to_le
  8. rsxx_save_config
  9. rsxx_load_config

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3 * Filename: config.c
   4 *
   5 * Authors: Joshua Morris <josh.h.morris@us.ibm.com>
   6 *       Philip Kelleher <pjk1939@linux.vnet.ibm.com>
   7 *
   8 * (C) Copyright 2013 IBM Corporation
   9 */
  10 
  11 #include <linux/types.h>
  12 #include <linux/crc32.h>
  13 #include <linux/swab.h>
  14 
  15 #include "rsxx_priv.h"
  16 #include "rsxx_cfg.h"
  17 
  18 static void initialize_config(struct rsxx_card_cfg *cfg)
  19 {
  20         cfg->hdr.version = RSXX_CFG_VERSION;
  21 
  22         cfg->data.block_size        = RSXX_HW_BLK_SIZE;
  23         cfg->data.stripe_size       = RSXX_HW_BLK_SIZE;
  24         cfg->data.vendor_id         = RSXX_VENDOR_ID_IBM;
  25         cfg->data.cache_order       = (-1);
  26         cfg->data.intr_coal.mode    = RSXX_INTR_COAL_DISABLED;
  27         cfg->data.intr_coal.count   = 0;
  28         cfg->data.intr_coal.latency = 0;
  29 }
  30 
  31 static u32 config_data_crc32(struct rsxx_card_cfg *cfg)
  32 {
  33         /*
  34          * Return the compliment of the CRC to ensure compatibility
  35          * (i.e. this is how early rsxx drivers did it.)
  36          */
  37 
  38         return ~crc32(~0, &cfg->data, sizeof(cfg->data));
  39 }
  40 
  41 
  42 /*----------------- Config Byte Swap Functions -------------------*/
  43 static void config_hdr_be_to_cpu(struct card_cfg_hdr *hdr)
  44 {
  45         hdr->version = be32_to_cpu((__force __be32) hdr->version);
  46         hdr->crc     = be32_to_cpu((__force __be32) hdr->crc);
  47 }
  48 
  49 static void config_hdr_cpu_to_be(struct card_cfg_hdr *hdr)
  50 {
  51         hdr->version = (__force u32) cpu_to_be32(hdr->version);
  52         hdr->crc     = (__force u32) cpu_to_be32(hdr->crc);
  53 }
  54 
  55 static void config_data_swab(struct rsxx_card_cfg *cfg)
  56 {
  57         u32 *data = (u32 *) &cfg->data;
  58         int i;
  59 
  60         for (i = 0; i < (sizeof(cfg->data) / 4); i++)
  61                 data[i] = swab32(data[i]);
  62 }
  63 
  64 static void config_data_le_to_cpu(struct rsxx_card_cfg *cfg)
  65 {
  66         u32 *data = (u32 *) &cfg->data;
  67         int i;
  68 
  69         for (i = 0; i < (sizeof(cfg->data) / 4); i++)
  70                 data[i] = le32_to_cpu((__force __le32) data[i]);
  71 }
  72 
  73 static void config_data_cpu_to_le(struct rsxx_card_cfg *cfg)
  74 {
  75         u32 *data = (u32 *) &cfg->data;
  76         int i;
  77 
  78         for (i = 0; i < (sizeof(cfg->data) / 4); i++)
  79                 data[i] = (__force u32) cpu_to_le32(data[i]);
  80 }
  81 
  82 
  83 /*----------------- Config Operations ------------------*/
  84 static int rsxx_save_config(struct rsxx_cardinfo *card)
  85 {
  86         struct rsxx_card_cfg cfg;
  87         int st;
  88 
  89         memcpy(&cfg, &card->config, sizeof(cfg));
  90 
  91         if (unlikely(cfg.hdr.version != RSXX_CFG_VERSION)) {
  92                 dev_err(CARD_TO_DEV(card),
  93                         "Cannot save config with invalid version %d\n",
  94                         cfg.hdr.version);
  95                 return -EINVAL;
  96         }
  97 
  98         /* Convert data to little endian for the CRC calculation. */
  99         config_data_cpu_to_le(&cfg);
 100 
 101         cfg.hdr.crc = config_data_crc32(&cfg);
 102 
 103         /*
 104          * Swap the data from little endian to big endian so it can be
 105          * stored.
 106          */
 107         config_data_swab(&cfg);
 108         config_hdr_cpu_to_be(&cfg.hdr);
 109 
 110         st = rsxx_creg_write(card, CREG_ADD_CONFIG, sizeof(cfg), &cfg, 1);
 111         if (st)
 112                 return st;
 113 
 114         return 0;
 115 }
 116 
 117 int rsxx_load_config(struct rsxx_cardinfo *card)
 118 {
 119         int st;
 120         u32 crc;
 121 
 122         st = rsxx_creg_read(card, CREG_ADD_CONFIG, sizeof(card->config),
 123                                 &card->config, 1);
 124         if (st) {
 125                 dev_err(CARD_TO_DEV(card),
 126                         "Failed reading card config.\n");
 127                 return st;
 128         }
 129 
 130         config_hdr_be_to_cpu(&card->config.hdr);
 131 
 132         if (card->config.hdr.version == RSXX_CFG_VERSION) {
 133                 /*
 134                  * We calculate the CRC with the data in little endian, because
 135                  * early drivers did not take big endian CPUs into account.
 136                  * The data is always stored in big endian, so we need to byte
 137                  * swap it before calculating the CRC.
 138                  */
 139 
 140                 config_data_swab(&card->config);
 141 
 142                 /* Check the CRC */
 143                 crc = config_data_crc32(&card->config);
 144                 if (crc != card->config.hdr.crc) {
 145                         dev_err(CARD_TO_DEV(card),
 146                                 "Config corruption detected!\n");
 147                         dev_info(CARD_TO_DEV(card),
 148                                 "CRC (sb x%08x is x%08x)\n",
 149                                 card->config.hdr.crc, crc);
 150                         return -EIO;
 151                 }
 152 
 153                 /* Convert the data to CPU byteorder */
 154                 config_data_le_to_cpu(&card->config);
 155 
 156         } else if (card->config.hdr.version != 0) {
 157                 dev_err(CARD_TO_DEV(card),
 158                         "Invalid config version %d.\n",
 159                         card->config.hdr.version);
 160                 /*
 161                  * Config version changes require special handling from the
 162                  * user
 163                  */
 164                 return -EINVAL;
 165         } else {
 166                 dev_info(CARD_TO_DEV(card),
 167                         "Initializing card configuration.\n");
 168                 initialize_config(&card->config);
 169                 st = rsxx_save_config(card);
 170                 if (st)
 171                         return st;
 172         }
 173 
 174         card->config_valid = 1;
 175 
 176         dev_dbg(CARD_TO_DEV(card), "version:     x%08x\n",
 177                 card->config.hdr.version);
 178         dev_dbg(CARD_TO_DEV(card), "crc:         x%08x\n",
 179                 card->config.hdr.crc);
 180         dev_dbg(CARD_TO_DEV(card), "block_size:  x%08x\n",
 181                 card->config.data.block_size);
 182         dev_dbg(CARD_TO_DEV(card), "stripe_size: x%08x\n",
 183                 card->config.data.stripe_size);
 184         dev_dbg(CARD_TO_DEV(card), "vendor_id:   x%08x\n",
 185                 card->config.data.vendor_id);
 186         dev_dbg(CARD_TO_DEV(card), "cache_order: x%08x\n",
 187                 card->config.data.cache_order);
 188         dev_dbg(CARD_TO_DEV(card), "mode:        x%08x\n",
 189                 card->config.data.intr_coal.mode);
 190         dev_dbg(CARD_TO_DEV(card), "count:       x%08x\n",
 191                 card->config.data.intr_coal.count);
 192         dev_dbg(CARD_TO_DEV(card), "latency:     x%08x\n",
 193                  card->config.data.intr_coal.latency);
 194 
 195         return 0;
 196 }
 197 

/* [<][>][^][v][top][bottom][index][help] */