LCOV - code coverage report
Current view: top level - drivers/pci - vpd.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 9 268 3.4 %
Date: 2022-04-01 14:17:54 Functions: 2 23 8.7 %
Branches: 2 222 0.9 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * PCI VPD support
       4                 :            :  *
       5                 :            :  * Copyright (C) 2010 Broadcom Corporation.
       6                 :            :  */
       7                 :            : 
       8                 :            : #include <linux/pci.h>
       9                 :            : #include <linux/delay.h>
      10                 :            : #include <linux/export.h>
      11                 :            : #include <linux/sched/signal.h>
      12                 :            : #include "pci.h"
      13                 :            : 
      14                 :            : /* VPD access through PCI 2.2+ VPD capability */
      15                 :            : 
      16                 :            : struct pci_vpd_ops {
      17                 :            :         ssize_t (*read)(struct pci_dev *dev, loff_t pos, size_t count, void *buf);
      18                 :            :         ssize_t (*write)(struct pci_dev *dev, loff_t pos, size_t count, const void *buf);
      19                 :            :         int (*set_size)(struct pci_dev *dev, size_t len);
      20                 :            : };
      21                 :            : 
      22                 :            : struct pci_vpd {
      23                 :            :         const struct pci_vpd_ops *ops;
      24                 :            :         struct bin_attribute *attr;     /* Descriptor for sysfs VPD entry */
      25                 :            :         struct mutex    lock;
      26                 :            :         unsigned int    len;
      27                 :            :         u16             flag;
      28                 :            :         u8              cap;
      29                 :            :         unsigned int    busy:1;
      30                 :            :         unsigned int    valid:1;
      31                 :            : };
      32                 :            : 
      33                 :            : /**
      34                 :            :  * pci_read_vpd - Read one entry from Vital Product Data
      35                 :            :  * @dev:        pci device struct
      36                 :            :  * @pos:        offset in vpd space
      37                 :            :  * @count:      number of bytes to read
      38                 :            :  * @buf:        pointer to where to store result
      39                 :            :  */
      40                 :          0 : ssize_t pci_read_vpd(struct pci_dev *dev, loff_t pos, size_t count, void *buf)
      41                 :            : {
      42   [ #  #  #  #  :          0 :         if (!dev->vpd || !dev->vpd->ops)
          #  #  #  #  #  
                #  #  # ]
      43                 :            :                 return -ENODEV;
      44                 :          0 :         return dev->vpd->ops->read(dev, pos, count, buf);
      45                 :            : }
      46                 :            : EXPORT_SYMBOL(pci_read_vpd);
      47                 :            : 
      48                 :            : /**
      49                 :            :  * pci_write_vpd - Write entry to Vital Product Data
      50                 :            :  * @dev:        pci device struct
      51                 :            :  * @pos:        offset in vpd space
      52                 :            :  * @count:      number of bytes to write
      53                 :            :  * @buf:        buffer containing write data
      54                 :            :  */
      55                 :          0 : ssize_t pci_write_vpd(struct pci_dev *dev, loff_t pos, size_t count, const void *buf)
      56                 :            : {
      57   [ #  #  #  #  :          0 :         if (!dev->vpd || !dev->vpd->ops)
             #  #  #  # ]
      58                 :            :                 return -ENODEV;
      59                 :          0 :         return dev->vpd->ops->write(dev, pos, count, buf);
      60                 :            : }
      61                 :            : EXPORT_SYMBOL(pci_write_vpd);
      62                 :            : 
      63                 :            : /**
      64                 :            :  * pci_set_vpd_size - Set size of Vital Product Data space
      65                 :            :  * @dev:        pci device struct
      66                 :            :  * @len:        size of vpd space
      67                 :            :  */
      68                 :          0 : int pci_set_vpd_size(struct pci_dev *dev, size_t len)
      69                 :            : {
      70   [ #  #  #  #  :          0 :         if (!dev->vpd || !dev->vpd->ops)
          #  #  #  #  #  
                      # ]
      71                 :            :                 return -ENODEV;
      72                 :          0 :         return dev->vpd->ops->set_size(dev, len);
      73                 :            : }
      74                 :            : EXPORT_SYMBOL(pci_set_vpd_size);
      75                 :            : 
      76                 :            : #define PCI_VPD_MAX_SIZE (PCI_VPD_ADDR_MASK + 1)
      77                 :            : 
      78                 :            : /**
      79                 :            :  * pci_vpd_size - determine actual size of Vital Product Data
      80                 :            :  * @dev:        pci device struct
      81                 :            :  * @old_size:   current assumed size, also maximum allowed size
      82                 :            :  */
      83                 :          0 : static size_t pci_vpd_size(struct pci_dev *dev, size_t old_size)
      84                 :            : {
      85                 :          0 :         size_t off = 0;
      86                 :          0 :         unsigned char header[1+2];      /* 1 byte tag, 2 bytes length */
      87                 :            : 
      88   [ #  #  #  # ]:          0 :         while (off < old_size &&
      89         [ #  # ]:          0 :                pci_read_vpd(dev, off, 1, header) == 1) {
      90                 :          0 :                 unsigned char tag;
      91                 :            : 
      92         [ #  # ]:          0 :                 if (header[0] & PCI_VPD_LRDT) {
      93                 :            :                         /* Large Resource Data Type Tag */
      94         [ #  # ]:          0 :                         tag = pci_vpd_lrdt_tag(header);
      95                 :            :                         /* Only read length from known tag items */
      96                 :          0 :                         if ((tag == PCI_VPD_LTIN_ID_STRING) ||
      97   [ #  #  #  # ]:          0 :                             (tag == PCI_VPD_LTIN_RO_DATA) ||
      98                 :            :                             (tag == PCI_VPD_LTIN_RW_DATA)) {
      99   [ #  #  #  # ]:          0 :                                 if (pci_read_vpd(dev, off+1, 2,
     100                 :            :                                                  &header[1]) != 2) {
     101                 :          0 :                                         pci_warn(dev, "invalid large VPD tag %02x size at offset %zu",
     102                 :            :                                                  tag, off + 1);
     103                 :          0 :                                         return 0;
     104                 :            :                                 }
     105                 :          0 :                                 off += PCI_VPD_LRDT_TAG_SIZE +
     106                 :          0 :                                         pci_vpd_lrdt_size(header);
     107                 :            :                         }
     108                 :            :                 } else {
     109                 :            :                         /* Short Resource Data Type Tag */
     110                 :          0 :                         off += PCI_VPD_SRDT_TAG_SIZE +
     111                 :          0 :                                 pci_vpd_srdt_size(header);
     112                 :          0 :                         tag = pci_vpd_srdt_tag(header);
     113                 :            :                 }
     114                 :            : 
     115         [ #  # ]:          0 :                 if (tag == PCI_VPD_STIN_END)    /* End tag descriptor */
     116                 :          0 :                         return off;
     117                 :            : 
     118                 :          0 :                 if ((tag != PCI_VPD_LTIN_ID_STRING) &&
     119   [ #  #  #  # ]:          0 :                     (tag != PCI_VPD_LTIN_RO_DATA) &&
     120                 :            :                     (tag != PCI_VPD_LTIN_RW_DATA)) {
     121         [ #  # ]:          0 :                         pci_warn(dev, "invalid %s VPD tag %02x at offset %zu",
     122                 :            :                                  (header[0] & PCI_VPD_LRDT) ? "large" : "short",
     123                 :            :                                  tag, off);
     124                 :          0 :                         return 0;
     125                 :            :                 }
     126                 :            :         }
     127                 :            :         return 0;
     128                 :            : }
     129                 :            : 
     130                 :            : /*
     131                 :            :  * Wait for last operation to complete.
     132                 :            :  * This code has to spin since there is no other notification from the PCI
     133                 :            :  * hardware. Since the VPD is often implemented by serial attachment to an
     134                 :            :  * EEPROM, it may take many milliseconds to complete.
     135                 :            :  *
     136                 :            :  * Returns 0 on success, negative values indicate error.
     137                 :            :  */
     138                 :          0 : static int pci_vpd_wait(struct pci_dev *dev)
     139                 :            : {
     140                 :          0 :         struct pci_vpd *vpd = dev->vpd;
     141         [ #  # ]:          0 :         unsigned long timeout = jiffies + msecs_to_jiffies(125);
     142                 :          0 :         unsigned long max_sleep = 16;
     143                 :          0 :         u16 status;
     144                 :          0 :         int ret;
     145                 :            : 
     146         [ #  # ]:          0 :         if (!vpd->busy)
     147                 :            :                 return 0;
     148                 :            : 
     149                 :          0 :         do {
     150                 :          0 :                 ret = pci_user_read_config_word(dev, vpd->cap + PCI_VPD_ADDR,
     151                 :            :                                                 &status);
     152         [ #  # ]:          0 :                 if (ret < 0)
     153                 :          0 :                         return ret;
     154                 :            : 
     155         [ #  # ]:          0 :                 if ((status & PCI_VPD_ADDR_F) == vpd->flag) {
     156                 :          0 :                         vpd->busy = 0;
     157                 :          0 :                         return 0;
     158                 :            :                 }
     159                 :            : 
     160         [ #  # ]:          0 :                 if (fatal_signal_pending(current))
     161                 :            :                         return -EINTR;
     162                 :            : 
     163         [ #  # ]:          0 :                 if (time_after(jiffies, timeout))
     164                 :            :                         break;
     165                 :            : 
     166                 :          0 :                 usleep_range(10, max_sleep);
     167         [ #  # ]:          0 :                 if (max_sleep < 1024)
     168                 :          0 :                         max_sleep *= 2;
     169                 :            :         } while (true);
     170                 :            : 
     171                 :          0 :         pci_warn(dev, "VPD access failed.  This is likely a firmware bug on this device.  Contact the card vendor for a firmware update\n");
     172                 :          0 :         return -ETIMEDOUT;
     173                 :            : }
     174                 :            : 
     175                 :          0 : static ssize_t pci_vpd_read(struct pci_dev *dev, loff_t pos, size_t count,
     176                 :            :                             void *arg)
     177                 :            : {
     178                 :          0 :         struct pci_vpd *vpd = dev->vpd;
     179                 :          0 :         int ret;
     180                 :          0 :         loff_t end = pos + count;
     181                 :          0 :         u8 *buf = arg;
     182                 :            : 
     183         [ #  # ]:          0 :         if (pos < 0)
     184                 :            :                 return -EINVAL;
     185                 :            : 
     186         [ #  # ]:          0 :         if (!vpd->valid) {
     187                 :          0 :                 vpd->valid = 1;
     188                 :          0 :                 vpd->len = pci_vpd_size(dev, vpd->len);
     189                 :            :         }
     190                 :            : 
     191         [ #  # ]:          0 :         if (vpd->len == 0)
     192                 :            :                 return -EIO;
     193                 :            : 
     194         [ #  # ]:          0 :         if (pos > vpd->len)
     195                 :            :                 return 0;
     196                 :            : 
     197         [ #  # ]:          0 :         if (end > vpd->len) {
     198                 :          0 :                 end = vpd->len;
     199                 :          0 :                 count = end - pos;
     200                 :            :         }
     201                 :            : 
     202         [ #  # ]:          0 :         if (mutex_lock_killable(&vpd->lock))
     203                 :            :                 return -EINTR;
     204                 :            : 
     205                 :          0 :         ret = pci_vpd_wait(dev);
     206         [ #  # ]:          0 :         if (ret < 0)
     207                 :          0 :                 goto out;
     208                 :            : 
     209         [ #  # ]:          0 :         while (pos < end) {
     210                 :          0 :                 u32 val;
     211                 :          0 :                 unsigned int i, skip;
     212                 :            : 
     213                 :          0 :                 ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
     214                 :          0 :                                                  pos & ~3);
     215         [ #  # ]:          0 :                 if (ret < 0)
     216                 :            :                         break;
     217                 :          0 :                 vpd->busy = 1;
     218                 :          0 :                 vpd->flag = PCI_VPD_ADDR_F;
     219                 :          0 :                 ret = pci_vpd_wait(dev);
     220         [ #  # ]:          0 :                 if (ret < 0)
     221                 :            :                         break;
     222                 :            : 
     223                 :          0 :                 ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA, &val);
     224         [ #  # ]:          0 :                 if (ret < 0)
     225                 :            :                         break;
     226                 :            : 
     227                 :          0 :                 skip = pos & 3;
     228         [ #  # ]:          0 :                 for (i = 0;  i < sizeof(u32); i++) {
     229         [ #  # ]:          0 :                         if (i >= skip) {
     230                 :          0 :                                 *buf++ = val;
     231         [ #  # ]:          0 :                                 if (++pos == end)
     232                 :            :                                         break;
     233                 :            :                         }
     234                 :          0 :                         val >>= 8;
     235                 :            :                 }
     236                 :            :         }
     237                 :          0 : out:
     238                 :          0 :         mutex_unlock(&vpd->lock);
     239         [ #  # ]:          0 :         return ret ? ret : count;
     240                 :            : }
     241                 :            : 
     242                 :          0 : static ssize_t pci_vpd_write(struct pci_dev *dev, loff_t pos, size_t count,
     243                 :            :                              const void *arg)
     244                 :            : {
     245                 :          0 :         struct pci_vpd *vpd = dev->vpd;
     246                 :          0 :         const u8 *buf = arg;
     247                 :          0 :         loff_t end = pos + count;
     248                 :          0 :         int ret = 0;
     249                 :            : 
     250   [ #  #  #  #  :          0 :         if (pos < 0 || (pos & 3) || (count & 3))
                   #  # ]
     251                 :            :                 return -EINVAL;
     252                 :            : 
     253         [ #  # ]:          0 :         if (!vpd->valid) {
     254                 :          0 :                 vpd->valid = 1;
     255                 :          0 :                 vpd->len = pci_vpd_size(dev, vpd->len);
     256                 :            :         }
     257                 :            : 
     258         [ #  # ]:          0 :         if (vpd->len == 0)
     259                 :            :                 return -EIO;
     260                 :            : 
     261         [ #  # ]:          0 :         if (end > vpd->len)
     262                 :            :                 return -EINVAL;
     263                 :            : 
     264         [ #  # ]:          0 :         if (mutex_lock_killable(&vpd->lock))
     265                 :            :                 return -EINTR;
     266                 :            : 
     267                 :          0 :         ret = pci_vpd_wait(dev);
     268         [ #  # ]:          0 :         if (ret < 0)
     269                 :          0 :                 goto out;
     270                 :            : 
     271         [ #  # ]:          0 :         while (pos < end) {
     272                 :          0 :                 u32 val;
     273                 :            : 
     274                 :          0 :                 val = *buf++;
     275                 :          0 :                 val |= *buf++ << 8;
     276                 :          0 :                 val |= *buf++ << 16;
     277                 :          0 :                 val |= *buf++ << 24;
     278                 :            : 
     279                 :          0 :                 ret = pci_user_write_config_dword(dev, vpd->cap + PCI_VPD_DATA, val);
     280         [ #  # ]:          0 :                 if (ret < 0)
     281                 :            :                         break;
     282                 :          0 :                 ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR,
     283                 :          0 :                                                  pos | PCI_VPD_ADDR_F);
     284         [ #  # ]:          0 :                 if (ret < 0)
     285                 :            :                         break;
     286                 :            : 
     287                 :          0 :                 vpd->busy = 1;
     288                 :          0 :                 vpd->flag = 0;
     289                 :          0 :                 ret = pci_vpd_wait(dev);
     290         [ #  # ]:          0 :                 if (ret < 0)
     291                 :            :                         break;
     292                 :            : 
     293                 :          0 :                 pos += sizeof(u32);
     294                 :            :         }
     295                 :          0 : out:
     296                 :          0 :         mutex_unlock(&vpd->lock);
     297         [ #  # ]:          0 :         return ret ? ret : count;
     298                 :            : }
     299                 :            : 
     300                 :          0 : static int pci_vpd_set_size(struct pci_dev *dev, size_t len)
     301                 :            : {
     302                 :          0 :         struct pci_vpd *vpd = dev->vpd;
     303                 :            : 
     304         [ #  # ]:          0 :         if (len == 0 || len > PCI_VPD_MAX_SIZE)
     305                 :            :                 return -EIO;
     306                 :            : 
     307                 :          0 :         vpd->valid = 1;
     308                 :          0 :         vpd->len = len;
     309                 :            : 
     310                 :          0 :         return 0;
     311                 :            : }
     312                 :            : 
     313                 :            : static const struct pci_vpd_ops pci_vpd_ops = {
     314                 :            :         .read = pci_vpd_read,
     315                 :            :         .write = pci_vpd_write,
     316                 :            :         .set_size = pci_vpd_set_size,
     317                 :            : };
     318                 :            : 
     319                 :          0 : static ssize_t pci_vpd_f0_read(struct pci_dev *dev, loff_t pos, size_t count,
     320                 :            :                                void *arg)
     321                 :            : {
     322                 :          0 :         struct pci_dev *tdev = pci_get_slot(dev->bus,
     323                 :          0 :                                             PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
     324                 :          0 :         ssize_t ret;
     325                 :            : 
     326         [ #  # ]:          0 :         if (!tdev)
     327                 :            :                 return -ENODEV;
     328                 :            : 
     329         [ #  # ]:          0 :         ret = pci_read_vpd(tdev, pos, count, arg);
     330                 :          0 :         pci_dev_put(tdev);
     331                 :          0 :         return ret;
     332                 :            : }
     333                 :            : 
     334                 :          0 : static ssize_t pci_vpd_f0_write(struct pci_dev *dev, loff_t pos, size_t count,
     335                 :            :                                 const void *arg)
     336                 :            : {
     337                 :          0 :         struct pci_dev *tdev = pci_get_slot(dev->bus,
     338                 :          0 :                                             PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
     339                 :          0 :         ssize_t ret;
     340                 :            : 
     341         [ #  # ]:          0 :         if (!tdev)
     342                 :            :                 return -ENODEV;
     343                 :            : 
     344         [ #  # ]:          0 :         ret = pci_write_vpd(tdev, pos, count, arg);
     345                 :          0 :         pci_dev_put(tdev);
     346                 :          0 :         return ret;
     347                 :            : }
     348                 :            : 
     349                 :          0 : static int pci_vpd_f0_set_size(struct pci_dev *dev, size_t len)
     350                 :            : {
     351                 :          0 :         struct pci_dev *tdev = pci_get_slot(dev->bus,
     352                 :          0 :                                             PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
     353                 :          0 :         int ret;
     354                 :            : 
     355         [ #  # ]:          0 :         if (!tdev)
     356                 :            :                 return -ENODEV;
     357                 :            : 
     358         [ #  # ]:          0 :         ret = pci_set_vpd_size(tdev, len);
     359                 :          0 :         pci_dev_put(tdev);
     360                 :          0 :         return ret;
     361                 :            : }
     362                 :            : 
     363                 :            : static const struct pci_vpd_ops pci_vpd_f0_ops = {
     364                 :            :         .read = pci_vpd_f0_read,
     365                 :            :         .write = pci_vpd_f0_write,
     366                 :            :         .set_size = pci_vpd_f0_set_size,
     367                 :            : };
     368                 :            : 
     369                 :         77 : int pci_vpd_init(struct pci_dev *dev)
     370                 :            : {
     371                 :         77 :         struct pci_vpd *vpd;
     372                 :         77 :         u8 cap;
     373                 :            : 
     374                 :         77 :         cap = pci_find_capability(dev, PCI_CAP_ID_VPD);
     375         [ -  + ]:         77 :         if (!cap)
     376                 :            :                 return -ENODEV;
     377                 :            : 
     378                 :          0 :         vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC);
     379         [ #  # ]:          0 :         if (!vpd)
     380                 :            :                 return -ENOMEM;
     381                 :            : 
     382                 :          0 :         vpd->len = PCI_VPD_MAX_SIZE;
     383         [ #  # ]:          0 :         if (dev->dev_flags & PCI_DEV_FLAGS_VPD_REF_F0)
     384                 :          0 :                 vpd->ops = &pci_vpd_f0_ops;
     385                 :            :         else
     386                 :          0 :                 vpd->ops = &pci_vpd_ops;
     387                 :          0 :         mutex_init(&vpd->lock);
     388                 :          0 :         vpd->cap = cap;
     389                 :          0 :         vpd->busy = 0;
     390                 :          0 :         vpd->valid = 0;
     391                 :          0 :         dev->vpd = vpd;
     392                 :          0 :         return 0;
     393                 :            : }
     394                 :            : 
     395                 :          0 : void pci_vpd_release(struct pci_dev *dev)
     396                 :            : {
     397                 :          0 :         kfree(dev->vpd);
     398                 :          0 : }
     399                 :            : 
     400                 :          0 : static ssize_t read_vpd_attr(struct file *filp, struct kobject *kobj,
     401                 :            :                              struct bin_attribute *bin_attr, char *buf,
     402                 :            :                              loff_t off, size_t count)
     403                 :            : {
     404         [ #  # ]:          0 :         struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
     405                 :            : 
     406         [ #  # ]:          0 :         if (bin_attr->size > 0) {
     407         [ #  # ]:          0 :                 if (off > bin_attr->size)
     408                 :            :                         count = 0;
     409                 :          0 :                 else if (count > bin_attr->size - off)
     410                 :            :                         count = bin_attr->size - off;
     411                 :            :         }
     412                 :            : 
     413         [ #  # ]:          0 :         return pci_read_vpd(dev, off, count, buf);
     414                 :            : }
     415                 :            : 
     416                 :          0 : static ssize_t write_vpd_attr(struct file *filp, struct kobject *kobj,
     417                 :            :                               struct bin_attribute *bin_attr, char *buf,
     418                 :            :                               loff_t off, size_t count)
     419                 :            : {
     420         [ #  # ]:          0 :         struct pci_dev *dev = to_pci_dev(kobj_to_dev(kobj));
     421                 :            : 
     422         [ #  # ]:          0 :         if (bin_attr->size > 0) {
     423         [ #  # ]:          0 :                 if (off > bin_attr->size)
     424                 :            :                         count = 0;
     425                 :          0 :                 else if (count > bin_attr->size - off)
     426                 :            :                         count = bin_attr->size - off;
     427                 :            :         }
     428                 :            : 
     429         [ #  # ]:          0 :         return pci_write_vpd(dev, off, count, buf);
     430                 :            : }
     431                 :            : 
     432                 :         77 : void pcie_vpd_create_sysfs_dev_files(struct pci_dev *dev)
     433                 :            : {
     434                 :         77 :         int retval;
     435                 :         77 :         struct bin_attribute *attr;
     436                 :            : 
     437         [ -  + ]:         77 :         if (!dev->vpd)
     438                 :            :                 return;
     439                 :            : 
     440                 :          0 :         attr = kzalloc(sizeof(*attr), GFP_ATOMIC);
     441         [ #  # ]:          0 :         if (!attr)
     442                 :            :                 return;
     443                 :            : 
     444                 :          0 :         sysfs_bin_attr_init(attr);
     445                 :          0 :         attr->size = 0;
     446                 :          0 :         attr->attr.name = "vpd";
     447                 :          0 :         attr->attr.mode = S_IRUSR | S_IWUSR;
     448                 :          0 :         attr->read = read_vpd_attr;
     449                 :          0 :         attr->write = write_vpd_attr;
     450                 :          0 :         retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
     451         [ #  # ]:          0 :         if (retval) {
     452                 :          0 :                 kfree(attr);
     453                 :          0 :                 return;
     454                 :            :         }
     455                 :            : 
     456                 :          0 :         dev->vpd->attr = attr;
     457                 :            : }
     458                 :            : 
     459                 :          0 : void pcie_vpd_remove_sysfs_dev_files(struct pci_dev *dev)
     460                 :            : {
     461   [ #  #  #  # ]:          0 :         if (dev->vpd && dev->vpd->attr) {
     462                 :          0 :                 sysfs_remove_bin_file(&dev->dev.kobj, dev->vpd->attr);
     463                 :          0 :                 kfree(dev->vpd->attr);
     464                 :            :         }
     465                 :          0 : }
     466                 :            : 
     467                 :          0 : int pci_vpd_find_tag(const u8 *buf, unsigned int off, unsigned int len, u8 rdt)
     468                 :            : {
     469                 :          0 :         int i;
     470                 :            : 
     471         [ #  # ]:          0 :         for (i = off; i < len; ) {
     472                 :          0 :                 u8 val = buf[i];
     473                 :            : 
     474         [ #  # ]:          0 :                 if (val & PCI_VPD_LRDT) {
     475                 :            :                         /* Don't return success of the tag isn't complete */
     476         [ #  # ]:          0 :                         if (i + PCI_VPD_LRDT_TAG_SIZE > len)
     477                 :            :                                 break;
     478                 :            : 
     479         [ #  # ]:          0 :                         if (val == rdt)
     480                 :          0 :                                 return i;
     481                 :            : 
     482                 :          0 :                         i += PCI_VPD_LRDT_TAG_SIZE +
     483                 :          0 :                              pci_vpd_lrdt_size(&buf[i]);
     484                 :            :                 } else {
     485                 :          0 :                         u8 tag = val & ~PCI_VPD_SRDT_LEN_MASK;
     486                 :            : 
     487         [ #  # ]:          0 :                         if (tag == rdt)
     488                 :          0 :                                 return i;
     489                 :            : 
     490         [ #  # ]:          0 :                         if (tag == PCI_VPD_SRDT_END)
     491                 :            :                                 break;
     492                 :            : 
     493                 :          0 :                         i += PCI_VPD_SRDT_TAG_SIZE +
     494                 :          0 :                              pci_vpd_srdt_size(&buf[i]);
     495                 :            :                 }
     496                 :            :         }
     497                 :            : 
     498                 :            :         return -ENOENT;
     499                 :            : }
     500                 :            : EXPORT_SYMBOL_GPL(pci_vpd_find_tag);
     501                 :            : 
     502                 :          0 : int pci_vpd_find_info_keyword(const u8 *buf, unsigned int off,
     503                 :            :                               unsigned int len, const char *kw)
     504                 :            : {
     505                 :          0 :         int i;
     506                 :            : 
     507         [ #  # ]:          0 :         for (i = off; i + PCI_VPD_INFO_FLD_HDR_SIZE <= off + len;) {
     508         [ #  # ]:          0 :                 if (buf[i + 0] == kw[0] &&
     509         [ #  # ]:          0 :                     buf[i + 1] == kw[1])
     510                 :          0 :                         return i;
     511                 :            : 
     512                 :          0 :                 i += PCI_VPD_INFO_FLD_HDR_SIZE +
     513                 :          0 :                      pci_vpd_info_field_size(&buf[i]);
     514                 :            :         }
     515                 :            : 
     516                 :            :         return -ENOENT;
     517                 :            : }
     518                 :            : EXPORT_SYMBOL_GPL(pci_vpd_find_info_keyword);
     519                 :            : 
     520                 :            : #ifdef CONFIG_PCI_QUIRKS
     521                 :            : /*
     522                 :            :  * Quirk non-zero PCI functions to route VPD access through function 0 for
     523                 :            :  * devices that share VPD resources between functions.  The functions are
     524                 :            :  * expected to be identical devices.
     525                 :            :  */
     526                 :          0 : static void quirk_f0_vpd_link(struct pci_dev *dev)
     527                 :            : {
     528                 :          0 :         struct pci_dev *f0;
     529                 :            : 
     530         [ #  # ]:          0 :         if (!PCI_FUNC(dev->devfn))
     531                 :            :                 return;
     532                 :            : 
     533                 :          0 :         f0 = pci_get_slot(dev->bus, PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
     534         [ #  # ]:          0 :         if (!f0)
     535                 :            :                 return;
     536                 :            : 
     537   [ #  #  #  # ]:          0 :         if (f0->vpd && dev->class == f0->class &&
     538         [ #  # ]:          0 :             dev->vendor == f0->vendor && dev->device == f0->device)
     539                 :          0 :                 dev->dev_flags |= PCI_DEV_FLAGS_VPD_REF_F0;
     540                 :            : 
     541                 :          0 :         pci_dev_put(f0);
     542                 :            : }
     543                 :            : DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_INTEL, PCI_ANY_ID,
     544                 :            :                               PCI_CLASS_NETWORK_ETHERNET, 8, quirk_f0_vpd_link);
     545                 :            : 
     546                 :            : /*
     547                 :            :  * If a device follows the VPD format spec, the PCI core will not read or
     548                 :            :  * write past the VPD End Tag.  But some vendors do not follow the VPD
     549                 :            :  * format spec, so we can't tell how much data is safe to access.  Devices
     550                 :            :  * may behave unpredictably if we access too much.  Blacklist these devices
     551                 :            :  * so we don't touch VPD at all.
     552                 :            :  */
     553                 :          0 : static void quirk_blacklist_vpd(struct pci_dev *dev)
     554                 :            : {
     555         [ #  # ]:          0 :         if (dev->vpd) {
     556                 :          0 :                 dev->vpd->len = 0;
     557                 :          0 :                 pci_warn(dev, FW_BUG "disabling VPD access (can't determine size of non-standard VPD format)\n");
     558                 :            :         }
     559                 :          0 : }
     560                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0060, quirk_blacklist_vpd);
     561                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x007c, quirk_blacklist_vpd);
     562                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0413, quirk_blacklist_vpd);
     563                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0078, quirk_blacklist_vpd);
     564                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0079, quirk_blacklist_vpd);
     565                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0073, quirk_blacklist_vpd);
     566                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x0071, quirk_blacklist_vpd);
     567                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005b, quirk_blacklist_vpd);
     568                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x002f, quirk_blacklist_vpd);
     569                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005d, quirk_blacklist_vpd);
     570                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_LSI_LOGIC, 0x005f, quirk_blacklist_vpd);
     571                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATTANSIC, PCI_ANY_ID,
     572                 :            :                 quirk_blacklist_vpd);
     573                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_QLOGIC, 0x2261, quirk_blacklist_vpd);
     574                 :            : /*
     575                 :            :  * The Amazon Annapurna Labs 0x0031 device id is reused for other non Root Port
     576                 :            :  * device types, so the quirk is registered for the PCI_CLASS_BRIDGE_PCI class.
     577                 :            :  */
     578                 :            : DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_VENDOR_ID_AMAZON_ANNAPURNA_LABS, 0x0031,
     579                 :            :                               PCI_CLASS_BRIDGE_PCI, 8, quirk_blacklist_vpd);
     580                 :            : 
     581                 :            : /*
     582                 :            :  * For Broadcom 5706, 5708, 5709 rev. A nics, any read beyond the
     583                 :            :  * VPD end tag will hang the device.  This problem was initially
     584                 :            :  * observed when a vpd entry was created in sysfs
     585                 :            :  * ('/sys/bus/pci/devices/<id>/vpd').   A read to this sysfs entry
     586                 :            :  * will dump 32k of data.  Reading a full 32k will cause an access
     587                 :            :  * beyond the VPD end tag causing the device to hang.  Once the device
     588                 :            :  * is hung, the bnx2 driver will not be able to reset the device.
     589                 :            :  * We believe that it is legal to read beyond the end tag and
     590                 :            :  * therefore the solution is to limit the read/write length.
     591                 :            :  */
     592                 :          0 : static void quirk_brcm_570x_limit_vpd(struct pci_dev *dev)
     593                 :            : {
     594                 :            :         /*
     595                 :            :          * Only disable the VPD capability for 5706, 5706S, 5708,
     596                 :            :          * 5708S and 5709 rev. A
     597                 :            :          */
     598         [ #  # ]:          0 :         if ((dev->device == PCI_DEVICE_ID_NX2_5706) ||
     599         [ #  # ]:          0 :             (dev->device == PCI_DEVICE_ID_NX2_5706S) ||
     600         [ #  # ]:          0 :             (dev->device == PCI_DEVICE_ID_NX2_5708) ||
     601         [ #  # ]:          0 :             (dev->device == PCI_DEVICE_ID_NX2_5708S) ||
     602                 :          0 :             ((dev->device == PCI_DEVICE_ID_NX2_5709) &&
     603         [ #  # ]:          0 :              (dev->revision & 0xf0) == 0x0)) {
     604         [ #  # ]:          0 :                 if (dev->vpd)
     605                 :          0 :                         dev->vpd->len = 0x80;
     606                 :            :         }
     607                 :          0 : }
     608                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
     609                 :            :                         PCI_DEVICE_ID_NX2_5706,
     610                 :            :                         quirk_brcm_570x_limit_vpd);
     611                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
     612                 :            :                         PCI_DEVICE_ID_NX2_5706S,
     613                 :            :                         quirk_brcm_570x_limit_vpd);
     614                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
     615                 :            :                         PCI_DEVICE_ID_NX2_5708,
     616                 :            :                         quirk_brcm_570x_limit_vpd);
     617                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
     618                 :            :                         PCI_DEVICE_ID_NX2_5708S,
     619                 :            :                         quirk_brcm_570x_limit_vpd);
     620                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
     621                 :            :                         PCI_DEVICE_ID_NX2_5709,
     622                 :            :                         quirk_brcm_570x_limit_vpd);
     623                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_BROADCOM,
     624                 :            :                         PCI_DEVICE_ID_NX2_5709S,
     625                 :            :                         quirk_brcm_570x_limit_vpd);
     626                 :            : 
     627                 :          0 : static void quirk_chelsio_extend_vpd(struct pci_dev *dev)
     628                 :            : {
     629                 :          0 :         int chip = (dev->device & 0xf000) >> 12;
     630                 :          0 :         int func = (dev->device & 0x0f00) >>  8;
     631                 :          0 :         int prod = (dev->device & 0x00ff) >>  0;
     632                 :            : 
     633                 :            :         /*
     634                 :            :          * If this is a T3-based adapter, there's a 1KB VPD area at offset
     635                 :            :          * 0xc00 which contains the preferred VPD values.  If this is a T4 or
     636                 :            :          * later based adapter, the special VPD is at offset 0x400 for the
     637                 :            :          * Physical Functions (the SR-IOV Virtual Functions have no VPD
     638                 :            :          * Capabilities).  The PCI VPD Access core routines will normally
     639                 :            :          * compute the size of the VPD by parsing the VPD Data Structure at
     640                 :            :          * offset 0x000.  This will result in silent failures when attempting
     641                 :            :          * to accesses these other VPD areas which are beyond those computed
     642                 :            :          * limits.
     643                 :            :          */
     644         [ #  # ]:          0 :         if (chip == 0x0 && prod >= 0x20)
     645         [ #  # ]:          0 :                 pci_set_vpd_size(dev, 8192);
     646         [ #  # ]:          0 :         else if (chip >= 0x4 && func < 0x8)
     647         [ #  # ]:          0 :                 pci_set_vpd_size(dev, 2048);
     648                 :          0 : }
     649                 :            : 
     650                 :            : DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_CHELSIO, PCI_ANY_ID,
     651                 :            :                         quirk_chelsio_extend_vpd);
     652                 :            : 
     653                 :            : #endif

Generated by: LCOV version 1.14