root/drivers/scsi/isci/probe_roms.c

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

DEFINITIONS

This source file includes following definitions.
  1. isci_request_oprom
  2. isci_request_firmware
  3. get_efi
  4. isci_get_efi_var

   1 /*
   2  * This file is provided under a dual BSD/GPLv2 license.  When using or
   3  * redistributing this file, you may do so under either license.
   4  *
   5  * GPL LICENSE SUMMARY
   6  *
   7  * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
   8  *
   9  * This program is free software; you can redistribute it and/or modify
  10  * it under the terms of version 2 of the GNU General Public License as
  11  * published by the Free Software Foundation.
  12  *
  13  * This program is distributed in the hope that it will be useful, but
  14  * WITHOUT ANY WARRANTY; without even the implied warranty of
  15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16  * General Public License for more details.
  17  *
  18  * You should have received a copy of the GNU General Public License
  19  * along with this program; if not, write to the Free Software
  20  * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  21  * The full GNU General Public License is included in this distribution
  22  * in the file called LICENSE.GPL.
  23  */
  24 
  25 /* probe_roms - scan for oem parameters */
  26 
  27 #include <linux/kernel.h>
  28 #include <linux/firmware.h>
  29 #include <linux/uaccess.h>
  30 #include <linux/efi.h>
  31 #include <asm/probe_roms.h>
  32 
  33 #include "isci.h"
  34 #include "task.h"
  35 #include "probe_roms.h"
  36 
  37 static efi_char16_t isci_efivar_name[] = {
  38         'R', 's', 't', 'S', 'c', 'u', 'O'
  39 };
  40 
  41 struct isci_orom *isci_request_oprom(struct pci_dev *pdev)
  42 {
  43         void __iomem *oprom = pci_map_biosrom(pdev);
  44         struct isci_orom *rom = NULL;
  45         size_t len, i;
  46         int j;
  47         char oem_sig[4];
  48         struct isci_oem_hdr oem_hdr;
  49         u8 *tmp, sum;
  50 
  51         if (!oprom)
  52                 return NULL;
  53 
  54         len = pci_biosrom_size(pdev);
  55         rom = devm_kzalloc(&pdev->dev, sizeof(*rom), GFP_KERNEL);
  56         if (!rom) {
  57                 pci_unmap_biosrom(oprom);
  58                 dev_warn(&pdev->dev,
  59                          "Unable to allocate memory for orom\n");
  60                 return NULL;
  61         }
  62 
  63         for (i = 0; i < len && rom; i += ISCI_OEM_SIG_SIZE) {
  64                 memcpy_fromio(oem_sig, oprom + i, ISCI_OEM_SIG_SIZE);
  65 
  66                 /* we think we found the OEM table */
  67                 if (memcmp(oem_sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) == 0) {
  68                         size_t copy_len;
  69 
  70                         memcpy_fromio(&oem_hdr, oprom + i, sizeof(oem_hdr));
  71 
  72                         copy_len = min(oem_hdr.len - sizeof(oem_hdr),
  73                                        sizeof(*rom));
  74 
  75                         memcpy_fromio(rom,
  76                                       oprom + i + sizeof(oem_hdr),
  77                                       copy_len);
  78 
  79                         /* calculate checksum */
  80                         tmp = (u8 *)&oem_hdr;
  81                         for (j = 0, sum = 0; j < sizeof(oem_hdr); j++, tmp++)
  82                                 sum += *tmp;
  83 
  84                         tmp = (u8 *)rom;
  85                         for (j = 0; j < sizeof(*rom); j++, tmp++)
  86                                 sum += *tmp;
  87 
  88                         if (sum != 0) {
  89                                 dev_warn(&pdev->dev,
  90                                          "OEM table checksum failed\n");
  91                                 continue;
  92                         }
  93 
  94                         /* keep going if that's not the oem param table */
  95                         if (memcmp(rom->hdr.signature,
  96                                    ISCI_ROM_SIG,
  97                                    ISCI_ROM_SIG_SIZE) != 0)
  98                                 continue;
  99 
 100                         dev_info(&pdev->dev,
 101                                  "OEM parameter table found in OROM\n");
 102                         break;
 103                 }
 104         }
 105 
 106         if (i >= len) {
 107                 dev_err(&pdev->dev, "oprom parse error\n");
 108                 rom = NULL;
 109         }
 110         pci_unmap_biosrom(oprom);
 111 
 112         return rom;
 113 }
 114 
 115 struct isci_orom *isci_request_firmware(struct pci_dev *pdev, const struct firmware *fw)
 116 {
 117         struct isci_orom *orom = NULL, *data;
 118         int i, j;
 119 
 120         if (request_firmware(&fw, ISCI_FW_NAME, &pdev->dev) != 0)
 121                 return NULL;
 122 
 123         if (fw->size < sizeof(*orom))
 124                 goto out;
 125 
 126         data = (struct isci_orom *)fw->data;
 127 
 128         if (strncmp(ISCI_ROM_SIG, data->hdr.signature,
 129                     strlen(ISCI_ROM_SIG)) != 0)
 130                 goto out;
 131 
 132         orom = devm_kzalloc(&pdev->dev, fw->size, GFP_KERNEL);
 133         if (!orom)
 134                 goto out;
 135 
 136         memcpy(orom, fw->data, fw->size);
 137 
 138         if (is_c0(pdev) || is_c1(pdev))
 139                 goto out;
 140 
 141         /*
 142          * deprecated: override default amp_control for pre-preproduction
 143          * silicon revisions
 144          */
 145         for (i = 0; i < ARRAY_SIZE(orom->ctrl); i++)
 146                 for (j = 0; j < ARRAY_SIZE(orom->ctrl[i].phys); j++) {
 147                         orom->ctrl[i].phys[j].afe_tx_amp_control0 = 0xe7c03;
 148                         orom->ctrl[i].phys[j].afe_tx_amp_control1 = 0xe7c03;
 149                         orom->ctrl[i].phys[j].afe_tx_amp_control2 = 0xe7c03;
 150                         orom->ctrl[i].phys[j].afe_tx_amp_control3 = 0xe7c03;
 151                 }
 152  out:
 153         release_firmware(fw);
 154 
 155         return orom;
 156 }
 157 
 158 static struct efi *get_efi(void)
 159 {
 160 #ifdef CONFIG_EFI
 161         return &efi;
 162 #else
 163         return NULL;
 164 #endif
 165 }
 166 
 167 struct isci_orom *isci_get_efi_var(struct pci_dev *pdev)
 168 {
 169         efi_status_t status;
 170         struct isci_orom *rom;
 171         struct isci_oem_hdr *oem_hdr;
 172         u8 *tmp, sum;
 173         int j;
 174         unsigned long data_len;
 175         u8 *efi_data;
 176         u32 efi_attrib = 0;
 177 
 178         data_len = 1024;
 179         efi_data = devm_kzalloc(&pdev->dev, data_len, GFP_KERNEL);
 180         if (!efi_data) {
 181                 dev_warn(&pdev->dev,
 182                          "Unable to allocate memory for EFI data\n");
 183                 return NULL;
 184         }
 185 
 186         rom = (struct isci_orom *)(efi_data + sizeof(struct isci_oem_hdr));
 187 
 188         if (get_efi())
 189                 status = get_efi()->get_variable(isci_efivar_name,
 190                                                  &ISCI_EFI_VENDOR_GUID,
 191                                                  &efi_attrib,
 192                                                  &data_len,
 193                                                  efi_data);
 194         else
 195                 status = EFI_NOT_FOUND;
 196 
 197         if (status != EFI_SUCCESS) {
 198                 dev_warn(&pdev->dev,
 199                          "Unable to obtain EFI var data for OEM parms\n");
 200                 return NULL;
 201         }
 202 
 203         oem_hdr = (struct isci_oem_hdr *)efi_data;
 204 
 205         if (memcmp(oem_hdr->sig, ISCI_OEM_SIG, ISCI_OEM_SIG_SIZE) != 0) {
 206                 dev_warn(&pdev->dev,
 207                          "Invalid OEM header signature\n");
 208                 return NULL;
 209         }
 210 
 211         /* calculate checksum */
 212         tmp = (u8 *)efi_data;
 213         for (j = 0, sum = 0; j < (sizeof(*oem_hdr) + sizeof(*rom)); j++, tmp++)
 214                 sum += *tmp;
 215 
 216         if (sum != 0) {
 217                 dev_warn(&pdev->dev,
 218                          "OEM table checksum failed\n");
 219                 return NULL;
 220         }
 221 
 222         if (memcmp(rom->hdr.signature,
 223                    ISCI_ROM_SIG,
 224                    ISCI_ROM_SIG_SIZE) != 0) {
 225                 dev_warn(&pdev->dev,
 226                          "Invalid OEM table signature\n");
 227                 return NULL;
 228         }
 229 
 230         return rom;
 231 }

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