2018-01-26 21:50:27 +03:00
// SPDX-License-Identifier: GPL-2.0
2018-03-10 01:36:33 +03:00
/*
* Simple stub driver to reserve a PCI device
2008-11-26 08:17:13 +03:00
*
* Copyright ( C ) 2008 Red Hat , Inc .
* Author :
2013-11-14 22:28:18 +04:00
* Chris Wright
2008-11-26 08:17:13 +03:00
*
* Usage is simple , allocate a new id to the stub driver and bind the
* device to it . For example :
2013-11-14 22:28:18 +04:00
*
2008-11-26 08:17:13 +03:00
* # echo " 8086 10f5 " > / sys / bus / pci / drivers / pci - stub / new_id
* # echo - n 0000 : 00 : 19.0 > / sys / bus / pci / drivers / e1000e / unbind
* # echo - n 0000 : 00 : 19.0 > / sys / bus / pci / drivers / pci - stub / bind
* # ls - l / sys / bus / pci / devices / 0000 : 00 : 19.0 / driver
* . . . / 0000 : 00 : 19.0 / driver - > . . / . . / . . / bus / pci / drivers / pci - stub
*/
# include <linux/module.h>
# include <linux/pci.h>
2009-09-03 10:27:27 +04:00
static char ids [ 1024 ] __initdata ;
module_param_string ( ids , ids , sizeof ( ids ) , 0 ) ;
MODULE_PARM_DESC ( ids , " Initial PCI IDs to add to the stub driver, format is "
" \" vendor:device[:subvendor[:subdevice[:class[:class_mask]]]] \" "
" and multiple comma separated entries can be specified " ) ;
2008-11-26 08:17:13 +03:00
static int pci_stub_probe ( struct pci_dev * dev , const struct pci_device_id * id )
{
2018-01-18 21:55:24 +03:00
pci_info ( dev , " claimed by stub \n " ) ;
2008-11-26 08:17:13 +03:00
return 0 ;
}
static struct pci_driver stub_driver = {
. name = " pci-stub " ,
. id_table = NULL , /* only dynamic id's */
. probe = pci_stub_probe ,
} ;
static int __init pci_stub_init ( void )
{
2009-09-03 10:27:27 +04:00
char * p , * id ;
int rc ;
rc = pci_register_driver ( & stub_driver ) ;
if ( rc )
return rc ;
2010-11-17 23:10:40 +03:00
/* no ids passed actually */
if ( ids [ 0 ] = = ' \0 ' )
return 0 ;
2009-09-03 10:27:27 +04:00
/* add ids specified in the module parameter */
p = ids ;
while ( ( id = strsep ( & p , " , " ) ) ) {
unsigned int vendor , device , subvendor = PCI_ANY_ID ,
2014-04-19 04:13:49 +04:00
subdevice = PCI_ANY_ID , class = 0 , class_mask = 0 ;
2009-09-03 10:27:27 +04:00
int fields ;
2010-12-22 12:06:36 +03:00
if ( ! strlen ( id ) )
continue ;
2009-09-03 10:27:27 +04:00
fields = sscanf ( id , " %x:%x:%x:%x:%x:%x " ,
& vendor , & device , & subvendor , & subdevice ,
& class , & class_mask ) ;
if ( fields < 2 ) {
2019-04-20 07:03:46 +03:00
pr_warn ( " pci-stub: invalid ID string \" %s \" \n " , id ) ;
2009-09-03 10:27:27 +04:00
continue ;
}
2019-04-20 07:03:46 +03:00
pr_info ( " pci-stub: add %04X:%04X sub=%04X:%04X cls=%08X/%08X \n " ,
2009-09-03 10:27:27 +04:00
vendor , device , subvendor , subdevice , class , class_mask ) ;
rc = pci_add_dynid ( & stub_driver , vendor , device ,
subvendor , subdevice , class , class_mask , 0 ) ;
if ( rc )
2019-04-20 07:03:46 +03:00
pr_warn ( " pci-stub: failed to add dynamic ID (%d) \n " ,
rc ) ;
2009-09-03 10:27:27 +04:00
}
return 0 ;
2008-11-26 08:17:13 +03:00
}
static void __exit pci_stub_exit ( void )
{
pci_unregister_driver ( & stub_driver ) ;
}
module_init ( pci_stub_init ) ;
module_exit ( pci_stub_exit ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Chris Wright <chrisw@sous-sol.org> " ) ;