Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * PCI Backend - Handles the virtual fields found on the capability lists
0004  *               in the configuration space.
0005  *
0006  * Author: Ryan Wilson <hap9@epoch.ncsc.mil>
0007  */
0008 
0009 #include <linux/kernel.h>
0010 #include <linux/pci.h>
0011 #include "pciback.h"
0012 #include "conf_space.h"
0013 
0014 static LIST_HEAD(capabilities);
0015 struct xen_pcibk_config_capability {
0016     struct list_head cap_list;
0017 
0018     int capability;
0019 
0020     /* If the device has the capability found above, add these fields */
0021     const struct config_field *fields;
0022 };
0023 
0024 static const struct config_field caplist_header[] = {
0025     {
0026      .offset    = PCI_CAP_LIST_ID,
0027      .size      = 2, /* encompass PCI_CAP_LIST_ID & PCI_CAP_LIST_NEXT */
0028      .u.w.read  = xen_pcibk_read_config_word,
0029      .u.w.write = NULL,
0030     },
0031     {}
0032 };
0033 
0034 static inline void register_capability(struct xen_pcibk_config_capability *cap)
0035 {
0036     list_add_tail(&cap->cap_list, &capabilities);
0037 }
0038 
0039 int xen_pcibk_config_capability_add_fields(struct pci_dev *dev)
0040 {
0041     int err = 0;
0042     struct xen_pcibk_config_capability *cap;
0043     int cap_offset;
0044 
0045     list_for_each_entry(cap, &capabilities, cap_list) {
0046         cap_offset = pci_find_capability(dev, cap->capability);
0047         if (cap_offset) {
0048             dev_dbg(&dev->dev, "Found capability 0x%x at 0x%x\n",
0049                 cap->capability, cap_offset);
0050 
0051             err = xen_pcibk_config_add_fields_offset(dev,
0052                                    caplist_header,
0053                                    cap_offset);
0054             if (err)
0055                 goto out;
0056             err = xen_pcibk_config_add_fields_offset(dev,
0057                                    cap->fields,
0058                                    cap_offset);
0059             if (err)
0060                 goto out;
0061         }
0062     }
0063 
0064 out:
0065     return err;
0066 }
0067 
0068 static int vpd_address_write(struct pci_dev *dev, int offset, u16 value,
0069                  void *data)
0070 {
0071     /* Disallow writes to the vital product data */
0072     if (value & PCI_VPD_ADDR_F)
0073         return PCIBIOS_SET_FAILED;
0074     else
0075         return pci_write_config_word(dev, offset, value);
0076 }
0077 
0078 static const struct config_field caplist_vpd[] = {
0079     {
0080      .offset    = PCI_VPD_ADDR,
0081      .size      = 2,
0082      .u.w.read  = xen_pcibk_read_config_word,
0083      .u.w.write = vpd_address_write,
0084      },
0085     {
0086      .offset     = PCI_VPD_DATA,
0087      .size       = 4,
0088      .u.dw.read  = xen_pcibk_read_config_dword,
0089      .u.dw.write = NULL,
0090      },
0091     {}
0092 };
0093 
0094 static int pm_caps_read(struct pci_dev *dev, int offset, u16 *value,
0095             void *data)
0096 {
0097     int err;
0098     u16 real_value;
0099 
0100     err = pci_read_config_word(dev, offset, &real_value);
0101     if (err)
0102         goto out;
0103 
0104     *value = real_value & ~PCI_PM_CAP_PME_MASK;
0105 
0106 out:
0107     return err;
0108 }
0109 
0110 /* PM_OK_BITS specifies the bits that the driver domain is allowed to change.
0111  * Can't allow driver domain to enable PMEs - they're shared */
0112 #define PM_OK_BITS (PCI_PM_CTRL_PME_STATUS|PCI_PM_CTRL_DATA_SEL_MASK)
0113 
0114 static int pm_ctrl_write(struct pci_dev *dev, int offset, u16 new_value,
0115              void *data)
0116 {
0117     int err;
0118     u16 old_value;
0119     pci_power_t new_state;
0120 
0121     err = pci_read_config_word(dev, offset, &old_value);
0122     if (err)
0123         goto out;
0124 
0125     new_state = (pci_power_t)(new_value & PCI_PM_CTRL_STATE_MASK);
0126 
0127     new_value &= PM_OK_BITS;
0128     if ((old_value & PM_OK_BITS) != new_value) {
0129         new_value = (old_value & ~PM_OK_BITS) | new_value;
0130         err = pci_write_config_word(dev, offset, new_value);
0131         if (err)
0132             goto out;
0133     }
0134 
0135     /* Let pci core handle the power management change */
0136     dev_dbg(&dev->dev, "set power state to %x\n", new_state);
0137     err = pci_set_power_state(dev, new_state);
0138     if (err) {
0139         err = PCIBIOS_SET_FAILED;
0140         goto out;
0141     }
0142 
0143  out:
0144     return err;
0145 }
0146 
0147 /* Ensure PMEs are disabled */
0148 static void *pm_ctrl_init(struct pci_dev *dev, int offset)
0149 {
0150     int err;
0151     u16 value;
0152 
0153     err = pci_read_config_word(dev, offset, &value);
0154     if (err)
0155         goto out;
0156 
0157     if (value & PCI_PM_CTRL_PME_ENABLE) {
0158         value &= ~PCI_PM_CTRL_PME_ENABLE;
0159         err = pci_write_config_word(dev, offset, value);
0160     }
0161 
0162 out:
0163     return err ? ERR_PTR(err) : NULL;
0164 }
0165 
0166 static const struct config_field caplist_pm[] = {
0167     {
0168         .offset     = PCI_PM_PMC,
0169         .size       = 2,
0170         .u.w.read   = pm_caps_read,
0171     },
0172     {
0173         .offset     = PCI_PM_CTRL,
0174         .size       = 2,
0175         .init       = pm_ctrl_init,
0176         .u.w.read   = xen_pcibk_read_config_word,
0177         .u.w.write  = pm_ctrl_write,
0178     },
0179     {
0180         .offset     = PCI_PM_PPB_EXTENSIONS,
0181         .size       = 1,
0182         .u.b.read   = xen_pcibk_read_config_byte,
0183     },
0184     {
0185         .offset     = PCI_PM_DATA_REGISTER,
0186         .size       = 1,
0187         .u.b.read   = xen_pcibk_read_config_byte,
0188     },
0189     {}
0190 };
0191 
0192 static struct msi_msix_field_config {
0193     u16          enable_bit; /* bit for enabling MSI/MSI-X */
0194     unsigned int int_type;   /* interrupt type for exclusiveness check */
0195 } msi_field_config = {
0196     .enable_bit = PCI_MSI_FLAGS_ENABLE,
0197     .int_type   = INTERRUPT_TYPE_MSI,
0198 }, msix_field_config = {
0199     .enable_bit = PCI_MSIX_FLAGS_ENABLE,
0200     .int_type   = INTERRUPT_TYPE_MSIX,
0201 };
0202 
0203 static void *msi_field_init(struct pci_dev *dev, int offset)
0204 {
0205     return &msi_field_config;
0206 }
0207 
0208 static void *msix_field_init(struct pci_dev *dev, int offset)
0209 {
0210     return &msix_field_config;
0211 }
0212 
0213 static int msi_msix_flags_write(struct pci_dev *dev, int offset, u16 new_value,
0214                 void *data)
0215 {
0216     int err;
0217     u16 old_value;
0218     const struct msi_msix_field_config *field_config = data;
0219     const struct xen_pcibk_dev_data *dev_data = pci_get_drvdata(dev);
0220 
0221     if (xen_pcibk_permissive || dev_data->permissive)
0222         goto write;
0223 
0224     err = pci_read_config_word(dev, offset, &old_value);
0225     if (err)
0226         return err;
0227 
0228     if (new_value == old_value)
0229         return 0;
0230 
0231     if (!dev_data->allow_interrupt_control ||
0232         (new_value ^ old_value) & ~field_config->enable_bit)
0233         return PCIBIOS_SET_FAILED;
0234 
0235     if (new_value & field_config->enable_bit) {
0236         /* don't allow enabling together with other interrupt types */
0237         int int_type = xen_pcibk_get_interrupt_type(dev);
0238 
0239         if (int_type == INTERRUPT_TYPE_NONE ||
0240             int_type == field_config->int_type)
0241             goto write;
0242         return PCIBIOS_SET_FAILED;
0243     }
0244 
0245 write:
0246     return pci_write_config_word(dev, offset, new_value);
0247 }
0248 
0249 static const struct config_field caplist_msix[] = {
0250     {
0251         .offset    = PCI_MSIX_FLAGS,
0252         .size      = 2,
0253         .init      = msix_field_init,
0254         .u.w.read  = xen_pcibk_read_config_word,
0255         .u.w.write = msi_msix_flags_write,
0256     },
0257     {}
0258 };
0259 
0260 static const struct config_field caplist_msi[] = {
0261     {
0262         .offset    = PCI_MSI_FLAGS,
0263         .size      = 2,
0264         .init      = msi_field_init,
0265         .u.w.read  = xen_pcibk_read_config_word,
0266         .u.w.write = msi_msix_flags_write,
0267     },
0268     {}
0269 };
0270 
0271 static struct xen_pcibk_config_capability xen_pcibk_config_capability_pm = {
0272     .capability = PCI_CAP_ID_PM,
0273     .fields = caplist_pm,
0274 };
0275 static struct xen_pcibk_config_capability xen_pcibk_config_capability_vpd = {
0276     .capability = PCI_CAP_ID_VPD,
0277     .fields = caplist_vpd,
0278 };
0279 static struct xen_pcibk_config_capability xen_pcibk_config_capability_msi = {
0280     .capability = PCI_CAP_ID_MSI,
0281     .fields = caplist_msi,
0282 };
0283 static struct xen_pcibk_config_capability xen_pcibk_config_capability_msix = {
0284     .capability = PCI_CAP_ID_MSIX,
0285     .fields = caplist_msix,
0286 };
0287 
0288 int xen_pcibk_config_capability_init(void)
0289 {
0290     register_capability(&xen_pcibk_config_capability_vpd);
0291     register_capability(&xen_pcibk_config_capability_pm);
0292     register_capability(&xen_pcibk_config_capability_msi);
0293     register_capability(&xen_pcibk_config_capability_msix);
0294 
0295     return 0;
0296 }