mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 12:52:29 -04:00
Merge branch 'pci/enumeration'
- Don't store pci_device_id in agp amd-k7 and via, ata, scsi nsp32, ipack tpci200, mlxsw since the dynamic ID feature means the ID is only guaranteed to live during probe (Gary Guo) - Add pci_match_one_id() to match an ID directly so dynamic ID insertion doesn't need to make a temporary device for matching (Gary Guo) - Check for existing ID inside the dynamic ID addition critical section to avoid a time-of-check vs time-of-use race (Gary Guo) - Copy device ID to avoid use-after-free when match races with sysfs dynamic ID removal (Gary Guo) * pci/enumeration: PCI: Fix UAF when probe runs concurrent to dyn ID removal PCI: Fix dyn_id add TOCTOU PCI: Make pci_match_one_device() match on ID instead of device agp/amd-k7: Don't rely on address of pci_device_id agp/via: Don't rely on address of pci_device_id mlxsw: pci: Don't store pci_device_id ipack: tpci200: Don't store pci_device_id scsi: nsp32: Don't store pci_device_id ata: ata_generic: Don't store pci_device_id
This commit is contained in:
@@ -51,11 +51,11 @@ enum {
|
||||
static int generic_set_mode(struct ata_link *link, struct ata_device **unused)
|
||||
{
|
||||
struct ata_port *ap = link->ap;
|
||||
const struct pci_device_id *id = ap->host->private_data;
|
||||
unsigned long driver_data = (unsigned long)ap->host->private_data;
|
||||
int dma_enabled = 0;
|
||||
struct ata_device *dev;
|
||||
|
||||
if (id->driver_data & ATA_GEN_FORCE_DMA) {
|
||||
if (driver_data & ATA_GEN_FORCE_DMA) {
|
||||
dma_enabled = 0xff;
|
||||
} else if (ap->ioaddr.bmdma_addr) {
|
||||
/* Bits 5 and 6 indicate if DMA is active on master/slave */
|
||||
@@ -206,7 +206,7 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id
|
||||
return rc;
|
||||
pcim_pin_device(dev);
|
||||
}
|
||||
return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id, 0);
|
||||
return ata_pci_bmdma_init_one(dev, ppi, &generic_sht, (void *)id->driver_data, 0);
|
||||
}
|
||||
|
||||
static const struct pci_device_id ata_generic[] = {
|
||||
|
||||
@@ -387,37 +387,17 @@ static const struct agp_bridge_driver amd_irongate_driver = {
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
static struct agp_device_ids amd_agp_device_ids[] =
|
||||
{
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006,
|
||||
.chipset_name = "Irongate",
|
||||
},
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_AMD_FE_GATE_700E,
|
||||
.chipset_name = "761",
|
||||
},
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_AMD_FE_GATE_700C,
|
||||
.chipset_name = "760MP",
|
||||
},
|
||||
{ }, /* dummy final entry, always present */
|
||||
};
|
||||
|
||||
static int agp_amdk7_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *ent)
|
||||
{
|
||||
struct agp_bridge_data *bridge;
|
||||
u8 cap_ptr;
|
||||
int j;
|
||||
|
||||
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
|
||||
if (!cap_ptr)
|
||||
return -ENODEV;
|
||||
|
||||
j = ent - agp_amdk7_pci_table;
|
||||
dev_info(&pdev->dev, "AMD %s chipset\n",
|
||||
amd_agp_device_ids[j].chipset_name);
|
||||
dev_info(&pdev->dev, "AMD %s chipset\n", (const char *)ent->driver_data);
|
||||
|
||||
bridge = agp_alloc_bridge();
|
||||
if (!bridge)
|
||||
@@ -492,7 +472,6 @@ static int agp_amdk7_resume(struct device *dev)
|
||||
return amd_irongate_driver.configure();
|
||||
}
|
||||
|
||||
/* must be the same order as name table above */
|
||||
static const struct pci_device_id agp_amdk7_pci_table[] = {
|
||||
{
|
||||
.class = (PCI_CLASS_BRIDGE_HOST << 8),
|
||||
@@ -501,6 +480,7 @@ static const struct pci_device_id agp_amdk7_pci_table[] = {
|
||||
.device = PCI_DEVICE_ID_AMD_FE_GATE_7006,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = (kernel_ulong_t)"Irongate",
|
||||
},
|
||||
{
|
||||
.class = (PCI_CLASS_BRIDGE_HOST << 8),
|
||||
@@ -509,6 +489,7 @@ static const struct pci_device_id agp_amdk7_pci_table[] = {
|
||||
.device = PCI_DEVICE_ID_AMD_FE_GATE_700E,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = (kernel_ulong_t)"761",
|
||||
},
|
||||
{
|
||||
.class = (PCI_CLASS_BRIDGE_HOST << 8),
|
||||
@@ -517,6 +498,7 @@ static const struct pci_device_id agp_amdk7_pci_table[] = {
|
||||
.device = PCI_DEVICE_ID_AMD_FE_GATE_700C,
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID,
|
||||
.driver_data = (kernel_ulong_t)"760MP",
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
@@ -221,204 +221,6 @@ static const struct agp_bridge_driver via_driver = {
|
||||
.agp_type_to_mask_type = agp_generic_type_to_mask_type,
|
||||
};
|
||||
|
||||
static struct agp_device_ids via_agp_device_ids[] =
|
||||
{
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_82C597_0,
|
||||
.chipset_name = "Apollo VP3",
|
||||
},
|
||||
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_82C598_0,
|
||||
.chipset_name = "Apollo MVP3",
|
||||
},
|
||||
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8501_0,
|
||||
.chipset_name = "Apollo MVP4",
|
||||
},
|
||||
|
||||
/* VT8601 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8601_0,
|
||||
.chipset_name = "Apollo ProMedia/PLE133Ta",
|
||||
},
|
||||
|
||||
/* VT82C693A / VT28C694T */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_82C691_0,
|
||||
.chipset_name = "Apollo Pro 133",
|
||||
},
|
||||
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8371_0,
|
||||
.chipset_name = "KX133",
|
||||
},
|
||||
|
||||
/* VT8633 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8633_0,
|
||||
.chipset_name = "Pro 266",
|
||||
},
|
||||
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_XN266,
|
||||
.chipset_name = "Apollo Pro266",
|
||||
},
|
||||
|
||||
/* VT8361 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8361,
|
||||
.chipset_name = "KLE133",
|
||||
},
|
||||
|
||||
/* VT8365 / VT8362 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8363_0,
|
||||
.chipset_name = "Twister-K/KT133x/KM133",
|
||||
},
|
||||
|
||||
/* VT8753A */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8753_0,
|
||||
.chipset_name = "P4X266",
|
||||
},
|
||||
|
||||
/* VT8366 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8367_0,
|
||||
.chipset_name = "KT266/KY266x/KT333",
|
||||
},
|
||||
|
||||
/* VT8633 (for CuMine/ Celeron) */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8653_0,
|
||||
.chipset_name = "Pro266T",
|
||||
},
|
||||
|
||||
/* KM266 / PM266 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_XM266,
|
||||
.chipset_name = "PM266/KM266",
|
||||
},
|
||||
|
||||
/* CLE266 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_862X_0,
|
||||
.chipset_name = "CLE266",
|
||||
},
|
||||
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8377_0,
|
||||
.chipset_name = "KT400/KT400A/KT600",
|
||||
},
|
||||
|
||||
/* VT8604 / VT8605 / VT8603
|
||||
* (Apollo Pro133A chipset with S3 Savage4) */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8605_0,
|
||||
.chipset_name = "ProSavage PM133/PL133/PN133"
|
||||
},
|
||||
|
||||
/* P4M266x/P4N266 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8703_51_0,
|
||||
.chipset_name = "P4M266x/P4N266",
|
||||
},
|
||||
|
||||
/* VT8754 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8754C_0,
|
||||
.chipset_name = "PT800",
|
||||
},
|
||||
|
||||
/* P4X600 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8763_0,
|
||||
.chipset_name = "P4X600"
|
||||
},
|
||||
|
||||
/* KM400 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8378_0,
|
||||
.chipset_name = "KM400/KM400A",
|
||||
},
|
||||
|
||||
/* PT880 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_PT880,
|
||||
.chipset_name = "PT880",
|
||||
},
|
||||
|
||||
/* PT880 Ultra */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_PT880ULTRA,
|
||||
.chipset_name = "PT880 Ultra",
|
||||
},
|
||||
|
||||
/* PT890 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_8783_0,
|
||||
.chipset_name = "PT890",
|
||||
},
|
||||
|
||||
/* PM800/PN800/PM880/PN880 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_PX8X0_0,
|
||||
.chipset_name = "PM800/PN800/PM880/PN880",
|
||||
},
|
||||
/* KT880 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_3269_0,
|
||||
.chipset_name = "KT880",
|
||||
},
|
||||
/* KTxxx/Px8xx */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_83_87XX_1,
|
||||
.chipset_name = "VT83xx/VT87xx/KTxxx/Px8xx",
|
||||
},
|
||||
/* P4M800 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_3296_0,
|
||||
.chipset_name = "P4M800",
|
||||
},
|
||||
/* P4M800CE */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_P4M800CE,
|
||||
.chipset_name = "VT3314",
|
||||
},
|
||||
/* VT3324 / CX700 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_VT3324,
|
||||
.chipset_name = "CX700",
|
||||
},
|
||||
/* VT3336 - this is a chipset for AMD Athlon/K8 CPU. Due to K8's unique
|
||||
* architecture, the AGP resource and behavior are different from
|
||||
* the traditional AGP which resides only in chipset. AGP is used
|
||||
* by 3D driver which wasn't available for the VT3336 and VT3364
|
||||
* generation until now. Unfortunately, by testing, VT3364 works
|
||||
* but VT3336 doesn't. - explanation from via, just leave this as
|
||||
* as a placeholder to avoid future patches adding it back in.
|
||||
*/
|
||||
#if 0
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_VT3336,
|
||||
.chipset_name = "VT3336",
|
||||
},
|
||||
#endif
|
||||
/* P4M890 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_P4M890,
|
||||
.chipset_name = "P4M890",
|
||||
},
|
||||
/* P4M900 */
|
||||
{
|
||||
.device_id = PCI_DEVICE_ID_VIA_VT3364,
|
||||
.chipset_name = "P4M900",
|
||||
},
|
||||
{ }, /* dummy final entry, always present */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* VIA's AGP3 chipsets do magick to put the AGP bridge compliant
|
||||
@@ -437,17 +239,14 @@ static void check_via_agp3 (struct agp_bridge_data *bridge)
|
||||
|
||||
static int agp_via_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||
{
|
||||
struct agp_device_ids *devs = via_agp_device_ids;
|
||||
struct agp_bridge_data *bridge;
|
||||
int j = 0;
|
||||
u8 cap_ptr;
|
||||
|
||||
cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP);
|
||||
if (!cap_ptr)
|
||||
return -ENODEV;
|
||||
|
||||
j = ent - agp_via_pci_table;
|
||||
printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name);
|
||||
dev_info(&pdev->dev, "Detected VIA %s chipset\n", (const char *)ent->driver_data);
|
||||
|
||||
bridge = agp_alloc_bridge();
|
||||
if (!bridge)
|
||||
@@ -501,9 +300,8 @@ static int agp_via_resume(struct device *dev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* must be the same order as name table above */
|
||||
static const struct pci_device_id agp_via_pci_table[] = {
|
||||
#define ID(x) \
|
||||
#define ID(x, name) \
|
||||
{ \
|
||||
.class = (PCI_CLASS_BRIDGE_HOST << 8), \
|
||||
.class_mask = ~0, \
|
||||
@@ -511,39 +309,77 @@ static const struct pci_device_id agp_via_pci_table[] = {
|
||||
.device = x, \
|
||||
.subvendor = PCI_ANY_ID, \
|
||||
.subdevice = PCI_ANY_ID, \
|
||||
.driver_data = (kernel_ulong_t)name, \
|
||||
}
|
||||
ID(PCI_DEVICE_ID_VIA_82C597_0),
|
||||
ID(PCI_DEVICE_ID_VIA_82C598_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8501_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8601_0),
|
||||
ID(PCI_DEVICE_ID_VIA_82C691_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8371_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8633_0),
|
||||
ID(PCI_DEVICE_ID_VIA_XN266),
|
||||
ID(PCI_DEVICE_ID_VIA_8361),
|
||||
ID(PCI_DEVICE_ID_VIA_8363_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8753_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8367_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8653_0),
|
||||
ID(PCI_DEVICE_ID_VIA_XM266),
|
||||
ID(PCI_DEVICE_ID_VIA_862X_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8377_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8605_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8703_51_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8754C_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8763_0),
|
||||
ID(PCI_DEVICE_ID_VIA_8378_0),
|
||||
ID(PCI_DEVICE_ID_VIA_PT880),
|
||||
ID(PCI_DEVICE_ID_VIA_PT880ULTRA),
|
||||
ID(PCI_DEVICE_ID_VIA_8783_0),
|
||||
ID(PCI_DEVICE_ID_VIA_PX8X0_0),
|
||||
ID(PCI_DEVICE_ID_VIA_3269_0),
|
||||
ID(PCI_DEVICE_ID_VIA_83_87XX_1),
|
||||
ID(PCI_DEVICE_ID_VIA_3296_0),
|
||||
ID(PCI_DEVICE_ID_VIA_P4M800CE),
|
||||
ID(PCI_DEVICE_ID_VIA_VT3324),
|
||||
ID(PCI_DEVICE_ID_VIA_P4M890),
|
||||
ID(PCI_DEVICE_ID_VIA_VT3364),
|
||||
ID(PCI_DEVICE_ID_VIA_82C597_0, "Apollo VP3"),
|
||||
ID(PCI_DEVICE_ID_VIA_82C598_0, "Apollo MVP3"),
|
||||
ID(PCI_DEVICE_ID_VIA_8501_0, "Apollo MVP4"),
|
||||
/* VT8601 */
|
||||
ID(PCI_DEVICE_ID_VIA_8601_0, "Apollo ProMedia/PLE133Ta"),
|
||||
/* VT82C693A / VT28C694T */
|
||||
ID(PCI_DEVICE_ID_VIA_82C691_0, "Apollo Pro 133"),
|
||||
ID(PCI_DEVICE_ID_VIA_8371_0, "KX133"),
|
||||
/* VT8633 */
|
||||
ID(PCI_DEVICE_ID_VIA_8633_0, "Pro 266"),
|
||||
ID(PCI_DEVICE_ID_VIA_XN266, "Apollo Pro266"),
|
||||
/* VT8361 */
|
||||
ID(PCI_DEVICE_ID_VIA_8361, "KLE133"),
|
||||
/* VT8365 / VT8362 */
|
||||
ID(PCI_DEVICE_ID_VIA_8363_0, "Twister-K/KT133x/KM133"),
|
||||
/* VT8753A */
|
||||
ID(PCI_DEVICE_ID_VIA_8753_0, "P4X266"),
|
||||
/* VT8366 */
|
||||
ID(PCI_DEVICE_ID_VIA_8367_0, "KT266/KY266x/KT333"),
|
||||
/* VT8633 (for CuMine/ Celeron) */
|
||||
ID(PCI_DEVICE_ID_VIA_8653_0, "Pro266T"),
|
||||
/* KM266 / PM266 */
|
||||
ID(PCI_DEVICE_ID_VIA_XM266, "PM266/KM266"),
|
||||
/* CLE266 */
|
||||
ID(PCI_DEVICE_ID_VIA_862X_0, "CLE266"),
|
||||
ID(PCI_DEVICE_ID_VIA_8377_0, "KT400/KT400A/KT600"),
|
||||
/* VT8604 / VT8605 / VT8603 (Apollo Pro133A chipset with S3 Savage4) */
|
||||
ID(PCI_DEVICE_ID_VIA_8605_0, "ProSavage PM133/PL133/PN133"),
|
||||
/* P4M266x/P4N266 */
|
||||
ID(PCI_DEVICE_ID_VIA_8703_51_0, "P4M266x/P4N266"),
|
||||
/* VT8754 */
|
||||
ID(PCI_DEVICE_ID_VIA_8754C_0, "PT800"),
|
||||
/* P4X600 */
|
||||
ID(PCI_DEVICE_ID_VIA_8763_0, "P4X600"),
|
||||
/* KM400 */
|
||||
ID(PCI_DEVICE_ID_VIA_8378_0, "KM400/KM400A"),
|
||||
/* PT880 */
|
||||
ID(PCI_DEVICE_ID_VIA_PT880, "PT880"),
|
||||
/* PT880 Ultra */
|
||||
ID(PCI_DEVICE_ID_VIA_PT880ULTRA, "PT880 Ultra"),
|
||||
/* PT890 */
|
||||
ID(PCI_DEVICE_ID_VIA_8783_0, "PT890"),
|
||||
/* PM800/PN800/PM880/PN880 */
|
||||
ID(PCI_DEVICE_ID_VIA_PX8X0_0, "PM800/PN800/PM880/PN880"),
|
||||
/* KT880 */
|
||||
ID(PCI_DEVICE_ID_VIA_3269_0, "KT880"),
|
||||
/* KTxxx/Px8xx */
|
||||
ID(PCI_DEVICE_ID_VIA_83_87XX_1, "VT83xx/VT87xx/KTxxx/Px8xx"),
|
||||
/* P4M800 */
|
||||
ID(PCI_DEVICE_ID_VIA_3296_0, "P4M800"),
|
||||
/* P4M800CE */
|
||||
ID(PCI_DEVICE_ID_VIA_P4M800CE, "VT3314"),
|
||||
/* VT3324 / CX700 */
|
||||
ID(PCI_DEVICE_ID_VIA_VT3324, "CX700"),
|
||||
/* VT3336 - this is a chipset for AMD Athlon/K8 CPU. Due to K8's unique
|
||||
* architecture, the AGP resource and behavior are different from
|
||||
* the traditional AGP which resides only in chipset. AGP is used
|
||||
* by 3D driver which wasn't available for the VT3336 and VT3364
|
||||
* generation until now. Unfortunately, by testing, VT3364 works
|
||||
* but VT3336 doesn't. - explanation from via, just leave this as
|
||||
* a placeholder to avoid future patches adding it back in.
|
||||
*/
|
||||
#if 0
|
||||
ID(PCI_DEVICE_ID_VIA_VT3336, "VT3336"),
|
||||
#endif
|
||||
/* P4M890 */
|
||||
ID(PCI_DEVICE_ID_VIA_P4M890, "P4M890"),
|
||||
/* P4M900 */
|
||||
ID(PCI_DEVICE_ID_VIA_VT3364, "P4M900"),
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
@@ -562,7 +562,6 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
|
||||
|
||||
/* Save struct pci_dev pointer */
|
||||
tpci200->info->pdev = pdev;
|
||||
tpci200->info->id_table = (struct pci_device_id *)id;
|
||||
|
||||
/* register the device and initialize it */
|
||||
ret = tpci200_install(tpci200);
|
||||
|
||||
@@ -145,7 +145,6 @@ struct tpci200_slot {
|
||||
*/
|
||||
struct tpci200_infos {
|
||||
struct pci_dev *pdev;
|
||||
struct pci_device_id *id_table;
|
||||
struct tpci200_regs __iomem *interface_regs;
|
||||
void __iomem *cfg_regs;
|
||||
struct ipack_bus_device *ipack_bus;
|
||||
|
||||
@@ -130,7 +130,6 @@ struct mlxsw_pci {
|
||||
} comp;
|
||||
} cmd;
|
||||
struct mlxsw_bus_info bus_info;
|
||||
const struct pci_device_id *id;
|
||||
enum mlxsw_pci_cqe_v max_cqe_ver; /* Maximal supported CQE version */
|
||||
u8 num_cqs; /* Number of CQs */
|
||||
u8 num_sdqs; /* Number of SDQs */
|
||||
@@ -1768,7 +1767,6 @@ static void mlxsw_pci_mbox_free(struct mlxsw_pci *mlxsw_pci,
|
||||
}
|
||||
|
||||
static int mlxsw_pci_sys_ready_wait(struct mlxsw_pci *mlxsw_pci,
|
||||
const struct pci_device_id *id,
|
||||
u32 *p_sys_status)
|
||||
{
|
||||
unsigned long end;
|
||||
@@ -1839,7 +1837,7 @@ static int mlxsw_pci_reset_sw(struct mlxsw_pci *mlxsw_pci)
|
||||
}
|
||||
|
||||
static int
|
||||
mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
|
||||
mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci)
|
||||
{
|
||||
struct pci_dev *pdev = mlxsw_pci->pdev;
|
||||
bool pci_reset_sbr_supported = false;
|
||||
@@ -1848,7 +1846,7 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
|
||||
u32 sys_status;
|
||||
int err;
|
||||
|
||||
err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status);
|
||||
err = mlxsw_pci_sys_ready_wait(mlxsw_pci, &sys_status);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to reach system ready status before reset. Status is 0x%x\n",
|
||||
sys_status);
|
||||
@@ -1880,7 +1878,7 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status);
|
||||
err = mlxsw_pci_sys_ready_wait(mlxsw_pci, &sys_status);
|
||||
if (err) {
|
||||
dev_err(&pdev->dev, "Failed to reach system ready status after reset. Status is 0x%x\n",
|
||||
sys_status);
|
||||
@@ -1932,7 +1930,7 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
|
||||
if (!mbox)
|
||||
return -ENOMEM;
|
||||
|
||||
err = mlxsw_pci_reset(mlxsw_pci, mlxsw_pci->id);
|
||||
err = mlxsw_pci_reset(mlxsw_pci);
|
||||
if (err)
|
||||
goto err_reset;
|
||||
|
||||
@@ -2464,7 +2462,6 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev);
|
||||
mlxsw_pci->bus_info.dev = &pdev->dev;
|
||||
mlxsw_pci->bus_info.read_clock_capable = true;
|
||||
mlxsw_pci->id = id;
|
||||
|
||||
err = mlxsw_core_bus_device_register(&mlxsw_pci->bus_info,
|
||||
&mlxsw_pci_bus, mlxsw_pci, false,
|
||||
|
||||
@@ -29,6 +29,47 @@ struct pci_dynid {
|
||||
struct pci_device_id id;
|
||||
};
|
||||
|
||||
/**
|
||||
* do_pci_add_dynid - Add a new PCI device ID to this driver and re-probe
|
||||
* @drv: target PCI driver
|
||||
* @id: ID to be added
|
||||
* @check_dup: whether to check if matching ID is already present
|
||||
*
|
||||
* Add a new dynamic PCI device ID to this driver and causes the driver to
|
||||
* probe for all devices again. @drv must have been registered prior to calling
|
||||
* this function.
|
||||
*
|
||||
* Context: Does GFP_KERNEL allocation.
|
||||
*
|
||||
* Return: 0 on success, -errno on failure.
|
||||
*/
|
||||
static int do_pci_add_dynid(struct pci_driver *drv,
|
||||
const struct pci_device_id *id,
|
||||
bool check_dup)
|
||||
{
|
||||
struct pci_dynid *dynid, *existing_dynid;
|
||||
|
||||
dynid = kzalloc_obj(*dynid);
|
||||
if (!dynid)
|
||||
return -ENOMEM;
|
||||
|
||||
dynid->id = *id;
|
||||
|
||||
scoped_guard(spinlock, &drv->dynids.lock) {
|
||||
if (check_dup) {
|
||||
list_for_each_entry(existing_dynid, &drv->dynids.list, node) {
|
||||
if (pci_match_one_id(&existing_dynid->id, id)) {
|
||||
kfree(dynid);
|
||||
return -EEXIST;
|
||||
}
|
||||
}
|
||||
}
|
||||
list_add_tail(&dynid->node, &drv->dynids.list);
|
||||
}
|
||||
|
||||
return driver_attach(&drv->driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_add_dynid - add a new PCI device ID to this driver and re-probe devices
|
||||
* @drv: target pci driver
|
||||
@@ -56,25 +97,17 @@ int pci_add_dynid(struct pci_driver *drv,
|
||||
unsigned int class, unsigned int class_mask,
|
||||
unsigned long driver_data)
|
||||
{
|
||||
struct pci_dynid *dynid;
|
||||
struct pci_device_id id = {
|
||||
.vendor = vendor,
|
||||
.device = device,
|
||||
.subvendor = subvendor,
|
||||
.subdevice = subdevice,
|
||||
.class = class,
|
||||
.class_mask = class_mask,
|
||||
.driver_data = driver_data,
|
||||
};
|
||||
|
||||
dynid = kzalloc_obj(*dynid);
|
||||
if (!dynid)
|
||||
return -ENOMEM;
|
||||
|
||||
dynid->id.vendor = vendor;
|
||||
dynid->id.device = device;
|
||||
dynid->id.subvendor = subvendor;
|
||||
dynid->id.subdevice = subdevice;
|
||||
dynid->id.class = class;
|
||||
dynid->id.class_mask = class_mask;
|
||||
dynid->id.driver_data = driver_data;
|
||||
|
||||
spin_lock(&drv->dynids.lock);
|
||||
list_add_tail(&dynid->node, &drv->dynids.list);
|
||||
spin_unlock(&drv->dynids.lock);
|
||||
|
||||
return driver_attach(&drv->driver);
|
||||
return do_pci_add_dynid(drv, &id, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pci_add_dynid);
|
||||
|
||||
@@ -90,6 +123,31 @@ static void pci_free_dynids(struct pci_driver *drv)
|
||||
spin_unlock(&drv->dynids.lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* do_pci_match_id - See if a PCI ID matches a given pci_id table
|
||||
* @ids: array of PCI device ID structures to search in
|
||||
* @dev_id: the actual PCI device ID structure to match against.
|
||||
* @include_override_only: also match against device ID entries marked as
|
||||
* override only.
|
||||
*
|
||||
* Return: the matching pci_device_id structure or %NULL if there is no match.
|
||||
*/
|
||||
static const struct pci_device_id *
|
||||
do_pci_match_id(const struct pci_device_id *ids,
|
||||
const struct pci_device_id *dev_id,
|
||||
bool include_override_only)
|
||||
{
|
||||
if (ids) {
|
||||
while (ids->vendor || ids->subvendor || ids->class_mask) {
|
||||
if ((!ids->override_only || include_override_only) &&
|
||||
pci_match_one_id(ids, dev_id))
|
||||
return ids;
|
||||
ids++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_match_id - See if a PCI device matches a given pci_id table
|
||||
* @ids: array of PCI device ID structures to search in
|
||||
@@ -105,14 +163,9 @@ static void pci_free_dynids(struct pci_driver *drv)
|
||||
const struct pci_device_id *pci_match_id(const struct pci_device_id *ids,
|
||||
struct pci_dev *dev)
|
||||
{
|
||||
if (ids) {
|
||||
while (ids->vendor || ids->subvendor || ids->class_mask) {
|
||||
if (pci_match_one_device(ids, dev))
|
||||
return ids;
|
||||
ids++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
struct pci_device_id dev_id = pci_id_from_device(dev);
|
||||
|
||||
return do_pci_match_id(ids, &dev_id, true);
|
||||
}
|
||||
EXPORT_SYMBOL(pci_match_id);
|
||||
|
||||
@@ -127,6 +180,7 @@ static const struct pci_device_id pci_device_id_any = {
|
||||
* pci_match_device - See if a device matches a driver's list of IDs
|
||||
* @drv: the PCI driver to match against
|
||||
* @dev: the PCI device structure to match against
|
||||
* @id_copy: place to store copy of pci_device_id for dynamic ID
|
||||
*
|
||||
* Used by a driver to check whether a PCI device is in its list of
|
||||
* supported devices or in the dynids list, which may have been augmented
|
||||
@@ -134,10 +188,11 @@ static const struct pci_device_id pci_device_id_any = {
|
||||
* structure or %NULL if there is no match.
|
||||
*/
|
||||
static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
|
||||
struct pci_dev *dev)
|
||||
struct pci_dev *dev,
|
||||
struct pci_device_id *id_copy)
|
||||
{
|
||||
struct pci_dynid *dynid;
|
||||
const struct pci_device_id *found_id = NULL, *ids;
|
||||
const struct pci_device_id *found_id = NULL;
|
||||
struct pci_device_id dev_id;
|
||||
int ret;
|
||||
|
||||
/* When driver_override is set, only bind to the matching driver */
|
||||
@@ -145,45 +200,29 @@ static const struct pci_device_id *pci_match_device(struct pci_driver *drv,
|
||||
if (ret == 0)
|
||||
return NULL;
|
||||
|
||||
dev_id = pci_id_from_device(dev);
|
||||
/* Look at the dynamic ids first, before the static ones */
|
||||
spin_lock(&drv->dynids.lock);
|
||||
list_for_each_entry(dynid, &drv->dynids.list, node) {
|
||||
if (pci_match_one_device(&dynid->id, dev)) {
|
||||
found_id = &dynid->id;
|
||||
break;
|
||||
scoped_guard(spinlock, &drv->dynids.lock) {
|
||||
struct pci_dynid *dynid;
|
||||
|
||||
list_for_each_entry(dynid, &drv->dynids.list, node) {
|
||||
if (pci_match_one_id(&dynid->id, &dev_id)) {
|
||||
*id_copy = dynid->id;
|
||||
return id_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&drv->dynids.lock);
|
||||
|
||||
found_id = do_pci_match_id(drv->id_table, &dev_id, ret > 0);
|
||||
if (found_id)
|
||||
return found_id;
|
||||
|
||||
for (ids = drv->id_table; (found_id = pci_match_id(ids, dev));
|
||||
ids = found_id + 1) {
|
||||
/*
|
||||
* The match table is split based on driver_override.
|
||||
* In case override_only was set, enforce driver_override
|
||||
* matching.
|
||||
*/
|
||||
if (found_id->override_only) {
|
||||
if (ret > 0)
|
||||
return found_id;
|
||||
} else {
|
||||
return found_id;
|
||||
}
|
||||
}
|
||||
|
||||
/* driver_override will always match, send a dummy id */
|
||||
if (ret > 0)
|
||||
return &pci_device_id_any;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _pci_free_device(struct device *dev)
|
||||
{
|
||||
kfree(to_pci_dev(dev));
|
||||
}
|
||||
|
||||
/**
|
||||
* new_id_store - sysfs frontend to pci_add_dynid()
|
||||
* @driver: target device driver
|
||||
@@ -197,38 +236,22 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf,
|
||||
{
|
||||
struct pci_driver *pdrv = to_pci_driver(driver);
|
||||
const struct pci_device_id *ids = pdrv->id_table;
|
||||
u32 vendor, device, subvendor = PCI_ANY_ID,
|
||||
subdevice = PCI_ANY_ID, class = 0, class_mask = 0;
|
||||
unsigned long driver_data = 0;
|
||||
struct pci_device_id id = {
|
||||
.subvendor = PCI_ANY_ID,
|
||||
.subdevice = PCI_ANY_ID
|
||||
};
|
||||
int fields;
|
||||
int retval = 0;
|
||||
|
||||
fields = sscanf(buf, "%x %x %x %x %x %x %lx",
|
||||
&vendor, &device, &subvendor, &subdevice,
|
||||
&class, &class_mask, &driver_data);
|
||||
&id.vendor, &id.device, &id.subvendor, &id.subdevice,
|
||||
&id.class, &id.class_mask, &id.driver_data);
|
||||
if (fields < 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (fields != 7) {
|
||||
struct pci_dev *pdev = kzalloc_obj(*pdev);
|
||||
if (!pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
pdev->vendor = vendor;
|
||||
pdev->device = device;
|
||||
pdev->subsystem_vendor = subvendor;
|
||||
pdev->subsystem_device = subdevice;
|
||||
pdev->class = class;
|
||||
pdev->dev.release = _pci_free_device;
|
||||
|
||||
device_initialize(&pdev->dev);
|
||||
if (pci_match_device(pdrv, pdev))
|
||||
retval = -EEXIST;
|
||||
|
||||
put_device(&pdev->dev);
|
||||
|
||||
if (retval)
|
||||
return retval;
|
||||
if (do_pci_match_id(pdrv->id_table, &id, false))
|
||||
return -EEXIST;
|
||||
}
|
||||
|
||||
/* Only accept driver_data values that match an existing id_table
|
||||
@@ -236,7 +259,7 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf,
|
||||
if (ids) {
|
||||
retval = -EINVAL;
|
||||
while (ids->vendor || ids->subvendor || ids->class_mask) {
|
||||
if (driver_data == ids->driver_data) {
|
||||
if (id.driver_data == ids->driver_data) {
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
@@ -246,8 +269,7 @@ static ssize_t new_id_store(struct device_driver *driver, const char *buf,
|
||||
return retval;
|
||||
}
|
||||
|
||||
retval = pci_add_dynid(pdrv, vendor, device, subvendor, subdevice,
|
||||
class, class_mask, driver_data);
|
||||
retval = do_pci_add_dynid(pdrv, &id, fields != 7);
|
||||
if (retval)
|
||||
return retval;
|
||||
return count;
|
||||
@@ -445,12 +467,13 @@ void pci_probe_flush_workqueue(void)
|
||||
static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
|
||||
{
|
||||
const struct pci_device_id *id;
|
||||
struct pci_device_id id_copy;
|
||||
int error = 0;
|
||||
|
||||
if (drv->probe) {
|
||||
error = -ENODEV;
|
||||
|
||||
id = pci_match_device(drv, pci_dev);
|
||||
id = pci_match_device(drv, pci_dev, &id_copy);
|
||||
if (id)
|
||||
error = pci_call_probe(drv, pci_dev, id);
|
||||
}
|
||||
@@ -1538,12 +1561,13 @@ static int pci_bus_match(struct device *dev, const struct device_driver *drv)
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
struct pci_driver *pci_drv;
|
||||
const struct pci_device_id *found_id;
|
||||
struct pci_device_id id_copy;
|
||||
|
||||
if (pci_dev_binding_disallowed(pci_dev))
|
||||
return 0;
|
||||
|
||||
pci_drv = (struct pci_driver *)to_pci_driver(drv);
|
||||
found_id = pci_match_device(pci_drv, pci_dev);
|
||||
found_id = pci_match_device(pci_drv, pci_dev, &id_copy);
|
||||
if (found_id)
|
||||
return 1;
|
||||
|
||||
|
||||
@@ -442,21 +442,40 @@ static inline int pci_setup_cardbus(char *str) { return -ENOENT; }
|
||||
#endif /* CONFIG_CARDBUS */
|
||||
|
||||
/**
|
||||
* pci_match_one_device - Tell if a PCI device structure has a matching
|
||||
* PCI device id structure
|
||||
* @id: single PCI device id structure to match
|
||||
* @dev: the PCI device structure to match against
|
||||
* pci_id_from_device - Obtain a pci_device_id from a PCI device
|
||||
* @dev: the PCI device
|
||||
*
|
||||
* Returns the matching pci_device_id structure or %NULL if there is no match.
|
||||
* Return: a pci_device_id filled.
|
||||
*/
|
||||
static inline struct pci_device_id pci_id_from_device(const struct pci_dev *dev)
|
||||
{
|
||||
return (struct pci_device_id) {
|
||||
.vendor = dev->vendor,
|
||||
.device = dev->device,
|
||||
.subvendor = dev->subsystem_vendor,
|
||||
.subdevice = dev->subsystem_device,
|
||||
.class = dev->class,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* pci_match_one_id - Tell if a PCI device ID matches a needle PCI device ID
|
||||
* @id: single PCI device id structure to match against (needle)
|
||||
* @dev_id: the actual ID from the PCI device
|
||||
*
|
||||
* ID can be retrieved from device using pci_id_from_device().
|
||||
*
|
||||
* Return: the matching pci_device_id structure or %NULL if there is no match.
|
||||
*/
|
||||
static inline const struct pci_device_id *
|
||||
pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev)
|
||||
pci_match_one_id(const struct pci_device_id *id,
|
||||
const struct pci_device_id *dev_id)
|
||||
{
|
||||
if ((id->vendor == PCI_ANY_ID || id->vendor == dev->vendor) &&
|
||||
(id->device == PCI_ANY_ID || id->device == dev->device) &&
|
||||
(id->subvendor == PCI_ANY_ID || id->subvendor == dev->subsystem_vendor) &&
|
||||
(id->subdevice == PCI_ANY_ID || id->subdevice == dev->subsystem_device) &&
|
||||
!((id->class ^ dev->class) & id->class_mask))
|
||||
if ((id->vendor == PCI_ANY_ID || id->vendor == dev_id->vendor) &&
|
||||
(id->device == PCI_ANY_ID || id->device == dev_id->device) &&
|
||||
(id->subvendor == PCI_ANY_ID || id->subvendor == dev_id->subvendor) &&
|
||||
(id->subdevice == PCI_ANY_ID || id->subdevice == dev_id->subdevice) &&
|
||||
!((id->class ^ dev_id->class) & id->class_mask))
|
||||
return id;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -245,8 +245,10 @@ static int match_pci_dev_by_id(struct device *dev, const void *data)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(dev);
|
||||
const struct pci_device_id *id = data;
|
||||
struct pci_device_id dev_id;
|
||||
|
||||
if (pci_match_one_device(id, pdev))
|
||||
dev_id = pci_id_from_device(pdev);
|
||||
if (pci_match_one_id(id, &dev_id))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -416,9 +418,9 @@ EXPORT_SYMBOL(pci_get_class);
|
||||
* @class: search for a PCI device with this base class code
|
||||
* @from: Previous PCI device found in search, or %NULL for new search.
|
||||
*
|
||||
* Iterates through the list of known PCI devices. If a PCI device is found
|
||||
* Iterate through the list of known PCI devices. If a PCI device is found
|
||||
* with a matching base class code, the reference count to the device is
|
||||
* incremented. See pci_match_one_device() to figure out how does this works.
|
||||
* incremented. See pci_match_one_id() to figure out how this works.
|
||||
* A new search is initiated by passing %NULL as the @from argument.
|
||||
* Otherwise if @from is not %NULL, searches continue from next device on the
|
||||
* global list. The reference count for @from is always decremented if it is
|
||||
|
||||
@@ -1470,7 +1470,7 @@ static int nsp32_show_info(struct seq_file *m, struct Scsi_Host *host)
|
||||
(nsp32_read2(base, INDEX_REG) >> 8) & 0xff);
|
||||
|
||||
mode_reg = nsp32_index_read1(base, CHIP_MODE);
|
||||
model = data->pci_devid->driver_data;
|
||||
model = data->model;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
seq_printf(m, "Power Management: %s\n",
|
||||
@@ -2907,8 +2907,8 @@ static int nsp32_eh_host_reset(struct scsi_cmnd *SCpnt)
|
||||
*/
|
||||
static int nsp32_getprom_param(nsp32_hw_data *data)
|
||||
{
|
||||
int vendor = data->pci_devid->vendor;
|
||||
int device = data->pci_devid->device;
|
||||
int vendor = data->Pci->vendor;
|
||||
int device = data->Pci->device;
|
||||
int ret, i;
|
||||
int __maybe_unused val;
|
||||
|
||||
@@ -3340,7 +3340,7 @@ static int nsp32_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
}
|
||||
|
||||
data->Pci = pdev;
|
||||
data->pci_devid = id;
|
||||
data->model = id->driver_data;
|
||||
data->IrqNumber = pdev->irq;
|
||||
data->BaseAddress = pci_resource_start(pdev, 0);
|
||||
data->NumAddress = pci_resource_len (pdev, 0);
|
||||
|
||||
@@ -564,10 +564,10 @@ typedef struct _nsp32_hw_data {
|
||||
|
||||
struct scsi_cmnd *CurrentSC;
|
||||
|
||||
struct pci_dev *Pci;
|
||||
const struct pci_device_id *pci_devid;
|
||||
struct Scsi_Host *Host;
|
||||
spinlock_t Lock;
|
||||
struct pci_dev *Pci;
|
||||
int model;
|
||||
struct Scsi_Host *Host;
|
||||
spinlock_t Lock;
|
||||
|
||||
char info_str[100];
|
||||
|
||||
|
||||
@@ -979,6 +979,7 @@ struct module;
|
||||
* function returns zero when the driver chooses to
|
||||
* take "ownership" of the device or an error code
|
||||
* (negative number) otherwise.
|
||||
* The pci_device_id parameter is only valid during probe.
|
||||
* The probe function always gets called from process
|
||||
* context, so it can sleep.
|
||||
* @remove: The remove() function gets called whenever a device
|
||||
|
||||
Reference in New Issue
Block a user