⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sgi_hotplug.c

📁 audio driver for hotplug pci on linux 2.6.27
💻 C
📖 第 1 页 / 共 2 页
字号:
			       __func__, ret);			/* try to continue on */		}	}	num_funcs = pci_scan_slot(slot->pci_bus,				  PCI_DEVFN(slot->device_num + 1, 0));	if (!num_funcs) {		dev_dbg(&slot->pci_bus->self->dev, "no device in slot\n");		mutex_unlock(&sn_hotplug_mutex);		return -ENODEV;	}	/*	 * Map SN resources for all functions on the card	 * to the Linux PCI interface and tell the drivers	 * about them.	 */	for (func = 0; func < num_funcs;  func++) {		dev = pci_get_slot(slot->pci_bus,				   PCI_DEVFN(slot->device_num + 1,					     PCI_FUNC(func)));		if (dev) {			/* Need to do slot fixup on PPB before fixup of children			 * (PPB's pcidev_info needs to be in pcidev_info list			 * before child's SN_PCIDEV_INFO() call to setup			 * pdi_host_pcidev_info).			 */			pcibios_fixup_device_resources(dev);			if (SN_ACPI_BASE_SUPPORT())				sn_acpi_slot_fixup(dev);			else				sn_io_slot_fixup(dev);			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {				unsigned char sec_bus;				pci_read_config_byte(dev, PCI_SECONDARY_BUS,						     &sec_bus);				new_bus = pci_add_new_bus(dev->bus, dev,							  sec_bus);				pci_scan_child_bus(new_bus);				new_ppb = 1;			}			pci_dev_put(dev);		}	}	/*	 * Add the slot's devices to the ACPI infrastructure */	if (SN_ACPI_BASE_SUPPORT() && ssdt) {		unsigned long long adr;		struct acpi_device *pdevice;		struct acpi_device *device;		acpi_handle phandle;		acpi_handle chandle = NULL;		acpi_handle rethandle;		acpi_status ret;		phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;		if (acpi_bus_get_device(phandle, &pdevice)) {			dev_dbg(&slot->pci_bus->self->dev,				"no parent device, assuming NULL\n");			pdevice = NULL;		}		/*		 * Walk the rootbus node's immediate children looking for		 * the slot's device node(s). There can be more than		 * one for multifunction devices.		 */		for (;;) {			rethandle = NULL;			ret = acpi_get_next_object(ACPI_TYPE_DEVICE,						   phandle, chandle,						   &rethandle);			if (ret == AE_NOT_FOUND || rethandle == NULL)				break;			chandle = rethandle;			ret = acpi_evaluate_integer(chandle, METHOD_NAME__ADR,						    NULL, &adr);			if (ACPI_SUCCESS(ret) &&			    (adr>>16) == (slot->device_num + 1)) {				ret = acpi_bus_add(&device, pdevice, chandle,						   ACPI_BUS_TYPE_DEVICE);				if (ACPI_FAILURE(ret)) {					printk(KERN_ERR "%s: acpi_bus_add "					       "failed (0x%x) for slot %d "					       "func %d\n", __func__,					       ret, (int)(adr>>16),					       (int)(adr&0xffff));					/* try to continue on */				} else {					acpi_bus_start(device);				}			}		}	}	/* Call the driver for the new device */	pci_bus_add_devices(slot->pci_bus);	/* Call the drivers for the new devices subordinate to PPB */	if (new_ppb)		pci_bus_add_devices(new_bus);	mutex_unlock(&sn_hotplug_mutex);	if (rc == 0)		dev_dbg(&slot->pci_bus->self->dev,			"insert operation successful\n");	else		dev_dbg(&slot->pci_bus->self->dev,			"insert operation failed rc = %d\n", rc);	return rc;}static int disable_slot(struct hotplug_slot *bss_hotplug_slot){	struct slot *slot = bss_hotplug_slot->private;	struct pci_dev *dev;	int func;	int rc;	acpi_owner_id ssdt_id = 0;	/* Acquire update access to the bus */	mutex_lock(&sn_hotplug_mutex);	/* is it okay to bring this slot down? */	rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,			     PCI_REQ_SLOT_ELIGIBLE);	if (rc)		goto leaving;	/* free the ACPI resources for the slot */	if (SN_ACPI_BASE_SUPPORT() &&            PCI_CONTROLLER(slot->pci_bus)->acpi_handle) {		unsigned long long adr;		struct acpi_device *device;		acpi_handle phandle;		acpi_handle chandle = NULL;		acpi_handle rethandle;		acpi_status ret;		/* Get the rootbus node pointer */		phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;		/*		 * Walk the rootbus node's immediate children looking for		 * the slot's device node(s). There can be more than		 * one for multifunction devices.		 */		for (;;) {			rethandle = NULL;			ret = acpi_get_next_object(ACPI_TYPE_DEVICE,						   phandle, chandle,						   &rethandle);			if (ret == AE_NOT_FOUND || rethandle == NULL)				break;			chandle = rethandle;			ret = acpi_evaluate_integer(chandle,						    METHOD_NAME__ADR,						    NULL, &adr);			if (ACPI_SUCCESS(ret) &&			    (adr>>16) == (slot->device_num + 1)) {				/* retain the owner id */				acpi_get_id(chandle, &ssdt_id);				ret = acpi_bus_get_device(chandle,							  &device);				if (ACPI_SUCCESS(ret))					acpi_bus_trim(device, 1);			}		}	}	/* Free the SN resources assigned to the Linux device.*/	for (func = 0; func < 8;  func++) {		dev = pci_get_slot(slot->pci_bus,				   PCI_DEVFN(slot->device_num + 1,				   	     PCI_FUNC(func)));		if (dev) {			sn_bus_free_data(dev);			pci_remove_bus_device(dev);			pci_dev_put(dev);		}	}	/* Remove the SSDT for the slot from the ACPI namespace */	if (SN_ACPI_BASE_SUPPORT() && ssdt_id) {		acpi_status ret;		ret = acpi_unload_table_id(ssdt_id);		if (ACPI_FAILURE(ret)) {			printk(KERN_ERR "%s: acpi_unload_table_id "			       "failed (0x%x) for id %d\n",			       __func__, ret, ssdt_id);			/* try to continue on */		}	}	/* free the collected sysdata pointers */	sn_bus_free_sysdata();	/* Deactivate slot */	rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,			     PCI_REQ_SLOT_DISABLE); leaving:	/* Release the bus lock */	mutex_unlock(&sn_hotplug_mutex);	return rc;}static inline int get_power_status(struct hotplug_slot *bss_hotplug_slot,				   u8 *value){	struct slot *slot = bss_hotplug_slot->private;	struct pcibus_info *pcibus_info;	u32 power;	pcibus_info = SN_PCIBUS_BUSSOFT_INFO(slot->pci_bus);	mutex_lock(&sn_hotplug_mutex);	power = pcibus_info->pbi_enabled_devices & (1 << slot->device_num);	*value = power ? 1 : 0;	mutex_unlock(&sn_hotplug_mutex);	return 0;}static void sn_release_slot(struct hotplug_slot *bss_hotplug_slot){	kfree(bss_hotplug_slot->info);	kfree(bss_hotplug_slot->private);	kfree(bss_hotplug_slot);}static int sn_hotplug_slot_register(struct pci_bus *pci_bus){	int device;	struct pci_slot *pci_slot;	struct hotplug_slot *bss_hotplug_slot;	char name[SN_SLOT_NAME_SIZE];	int rc = 0;	/*	 * Currently only four devices are supported,	 * in the future there maybe more -- up to 32.	 */	for (device = 0; device < SN_MAX_HP_SLOTS ; device++) {		if (sn_pci_slot_valid(pci_bus, device) != 1)			continue;		bss_hotplug_slot = kzalloc(sizeof(*bss_hotplug_slot),					   GFP_KERNEL);		if (!bss_hotplug_slot) {			rc = -ENOMEM;			goto alloc_err;		}		bss_hotplug_slot->info =			kzalloc(sizeof(struct hotplug_slot_info),				GFP_KERNEL);		if (!bss_hotplug_slot->info) {			rc = -ENOMEM;			goto alloc_err;		}		if (sn_hp_slot_private_alloc(bss_hotplug_slot,					     pci_bus, device, name)) {			rc = -ENOMEM;			goto alloc_err;		}		bss_hotplug_slot->ops = &sn_hotplug_slot_ops;		bss_hotplug_slot->release = &sn_release_slot;		rc = pci_hp_register(bss_hotplug_slot, pci_bus, device, name);		if (rc)			goto register_err;		pci_slot = bss_hotplug_slot->pci_slot;		rc = sysfs_create_file(&pci_slot->kobj,				       &sn_slot_path_attr.attr);		if (rc)			goto register_err;	}	dev_dbg(&pci_bus->self->dev, "Registered bus with hotplug\n");	return rc;register_err:	dev_dbg(&pci_bus->self->dev, "bus failed to register with err = %d\n",		rc);alloc_err:	if (rc == -ENOMEM)		dev_dbg(&pci_bus->self->dev, "Memory allocation error\n");	/* destroy THIS element */	if (bss_hotplug_slot)		sn_release_slot(bss_hotplug_slot);	/* destroy anything else on the list */	while ((bss_hotplug_slot = sn_hp_destroy()))		pci_hp_deregister(bss_hotplug_slot);	return rc;}static int sn_pci_hotplug_init(void){	struct pci_bus *pci_bus = NULL;	int rc;	int registered = 0;	if (!sn_prom_feature_available(PRF_HOTPLUG_SUPPORT)) {		printk(KERN_ERR "%s: PROM version does not support hotplug.\n",		       __func__);		return -EPERM;	}	INIT_LIST_HEAD(&sn_hp_list);	while ((pci_bus = pci_find_next_bus(pci_bus))) {		if (!pci_bus->sysdata)			continue;		rc = sn_pci_bus_valid(pci_bus);		if (rc != 1) {			dev_dbg(&pci_bus->self->dev, "not a valid hotplug bus\n");			continue;		}		dev_dbg(&pci_bus->self->dev, "valid hotplug bus\n");		rc = sn_hotplug_slot_register(pci_bus);		if (!rc) {			registered = 1;		} else {			registered = 0;			break;		}	}	return registered == 1 ? 0 : -ENODEV;}static void sn_pci_hotplug_exit(void){	struct hotplug_slot *bss_hotplug_slot;	while ((bss_hotplug_slot = sn_hp_destroy()))		pci_hp_deregister(bss_hotplug_slot);	if (!list_empty(&sn_hp_list))		printk(KERN_ERR "%s: internal list is not empty\n", __FILE__);}module_init(sn_pci_hotplug_init);module_exit(sn_pci_hotplug_exit);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -