Re: [patch 16/19] Altix: Add ACPI SSDT PCI device support (hotplug)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Acked-By: Len Brown <len.brown@xxxxxxxxx>

Tony,
This should probably be sent via your tree.

thanks,
-Len

On Tuesday 19 December 2006 15:56, akpm@xxxxxxxx wrote:
> From: John Keller <jpk@xxxxxxx>
> 
> Support for dynamic loading and unloading of ACPI SSDT tables upon slot
> hotplugs and unplugs.
> 
> On SN platforms, we now represent every populated root bus slot with a single
> ACPI SSDT table containing info for every device and PPB attached to the slot.
>  These SSDTs are generated by the prom at initial boot and hotplug time.  The
> info in these SSDT tables is used by the SN kernel IO "fixup" code (which is
> called at boot and hotplug time).
> 
> On hotplugs (i.e.  enable_slot()), if running with an ACPI capable prom,
> attempt to obtain a new ACPI SSDT table for the slot being hotplugged.  If
> successful, add the table to the ACPI namespace (acpi_load_table()) and then
> walk the new devices and add them to the ACPI infrastructure (acpi_bus_add()).
> 
> On hot unplugs (i.e.  disable_slot()), if running with an ACPI capable prom,
> attempt to remove the SSDT table associated with the slot from the ACPI
> namespace (acpi_unload_table_id()) and infastructure (acpi_bus_trim()).
> 
> From: John Keller <jpk@xxxxxxx>
> 
>  A bug was fixed where the sgi hotplug driver was removing
>  the slot's SSDT table from the ACPI namespace a bit too early in
>  disable_slot(). Also, we now call acpi_bus_start() subsequent
>  to acpi_bus_add().
> 
> Signed-off-by: Aaron Young <ayoung@xxxxxxx>
> Cc: "Brown, Len" <len.brown@xxxxxxxxx>
> Cc: Greg KH <greg@xxxxxxxxx>
> Cc: "Luck, Tony" <tony.luck@xxxxxxxxx>
> Signed-off-by: Andrew Morton <akpm@xxxxxxxx>
> ---
> 
>  drivers/pci/hotplug/sgi_hotplug.c |  155 ++++++++++++++++++++++++++--
>  1 files changed, 148 insertions(+), 7 deletions(-)
> 
> diff -puN drivers/pci/hotplug/sgi_hotplug.c~altix-add-acpi-ssdt-pci-device-support-hotplug drivers/pci/hotplug/sgi_hotplug.c
> --- a/drivers/pci/hotplug/sgi_hotplug.c~altix-add-acpi-ssdt-pci-device-support-hotplug
> +++ a/drivers/pci/hotplug/sgi_hotplug.c
> @@ -28,6 +28,8 @@
>  #include <asm/sn/sn_feature_sets.h>
>  #include <asm/sn/sn_sal.h>
>  #include <asm/sn/types.h>
> +#include <linux/acpi.h>
> +#include <asm/sn/acpi.h>
>  
>  #include "../pci.h"
>  
> @@ -35,14 +37,17 @@ MODULE_LICENSE("GPL");
>  MODULE_AUTHOR("SGI (prarit@xxxxxxx, dickie@xxxxxxx, habeck@xxxxxxx)");
>  MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
>  
> -#define PCIIO_ASIC_TYPE_TIOCA		4
> +
> +/* SAL call error codes. Keep in sync with prom header io/include/pcibr.h */
>  #define PCI_SLOT_ALREADY_UP		2	/* slot already up */
>  #define PCI_SLOT_ALREADY_DOWN		3	/* slot already down */
>  #define PCI_L1_ERR			7	/* L1 console command error */
>  #define PCI_EMPTY_33MHZ			15	/* empty 33 MHz bus */
> +
> +
> +#define PCIIO_ASIC_TYPE_TIOCA		4
>  #define PCI_L1_QSIZE			128	/* our L1 message buffer size */
>  #define SN_MAX_HP_SLOTS			32	/* max hotplug slots */
> -#define SGI_HOTPLUG_PROM_REV		0x0430	/* Min. required PROM version */
>  #define SN_SLOT_NAME_SIZE		33	/* size of name string */
>  
>  /* internal list head */
> @@ -227,7 +232,7 @@ static void sn_bus_free_data(struct pci_
>  }
>  
>  static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
> -			  int device_num)
> +			  int device_num, char **ssdt)
>  {
>  	struct slot *slot = bss_hotplug_slot->private;
>  	struct pcibus_info *pcibus_info;
> @@ -240,7 +245,8 @@ static int sn_slot_enable(struct hotplug
>  	 * Power-on and initialize the slot in the SN
>  	 * PCI infrastructure.
>  	 */
> -	rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp);
> +	rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp, ssdt);
> +
>  
>  	if (rc == PCI_SLOT_ALREADY_UP) {
>  		dev_dbg(slot->pci_bus->self, "is already active\n");
> @@ -335,6 +341,7 @@ static int enable_slot(struct hotplug_sl
>  	int func, num_funcs;
>  	int new_ppb = 0;
>  	int rc;
> +	char *ssdt = NULL;
>  	void pcibios_fixup_device_resources(struct pci_dev *);
>  
>  	/* Serialize the Linux PCI infrastructure */
> @@ -342,14 +349,29 @@ static int enable_slot(struct hotplug_sl
>  
>  	/*
>  	 * Power-on and initialize the slot in the SN
> -	 * PCI infrastructure.
> +	 * PCI infrastructure. Also, retrieve the ACPI SSDT
> +	 * table for the slot (if ACPI capable PROM).
>  	 */
> -	rc = sn_slot_enable(bss_hotplug_slot, slot->device_num);
> +	rc = sn_slot_enable(bss_hotplug_slot, slot->device_num, &ssdt);
>  	if (rc) {
>  		mutex_unlock(&sn_hotplug_mutex);
>  		return rc;
>  	}
>  
> +	if (ssdt)
> +		ssdt = __va(ssdt);
> +	/* Add the new SSDT for the slot to the ACPI namespace */
> +	if (SN_ACPI_BASE_SUPPORT() && ssdt) {
> +		acpi_status ret;
> +
> +		ret = acpi_load_table((struct acpi_table_header *)ssdt);
> +		if (ACPI_FAILURE(ret)) {
> +			printk(KERN_ERR "%s: acpi_load_table failed (0x%x)\n",
> +			       __FUNCTION__, ret);
> +			/* try to continue on */
> +		}
> +	}
> +
>  	num_funcs = pci_scan_slot(slot->pci_bus,
>  				  PCI_DEVFN(slot->device_num + 1, 0));
>  	if (!num_funcs) {
> @@ -374,7 +396,10 @@ static int enable_slot(struct hotplug_sl
>  			 * pdi_host_pcidev_info).
>  			 */
>  			pcibios_fixup_device_resources(dev);
> -			sn_pci_fixup_slot(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,
> @@ -388,6 +413,63 @@ static int enable_slot(struct hotplug_sl
>  		}
>  	}
>  
> +	/*
> +	 * Add the slot's devices to the ACPI infrastructure */
> +	if (SN_ACPI_BASE_SUPPORT() && ssdt) {
> +		unsigned 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,
> +				"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", __FUNCTION__,
> +					       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 */
> @@ -412,6 +494,7 @@ static int disable_slot(struct hotplug_s
>  	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);
> @@ -422,6 +505,52 @@ static int disable_slot(struct hotplug_s
>  	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 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,
> @@ -434,6 +563,18 @@ static int disable_slot(struct hotplug_s
>  		}
>  	}
>  
> +	/* 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(ACPI_TABLE_ID_SSDT, ssdt_id);
> +		if (ACPI_FAILURE(ret)) {
> +			printk(KERN_ERR "%s: acpi_unload_table_id "
> +			       "failed (0x%x) for id %d\n",
> +			       __FUNCTION__, ret, ssdt_id);
> +			/* try to continue on */
> +		}
> +	}
> +
>  	/* free the collected sysdata pointers */
>  	sn_bus_free_sysdata();
>  
> _
> -
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
-
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]

  Powered by Linux