Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * Standard Hot Plug Controller Driver
  3 *
  4 * Copyright (C) 1995,2001 Compaq Computer Corporation
  5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
  6 * Copyright (C) 2001 IBM Corp.
  7 * Copyright (C) 2003-2004 Intel Corporation
  8 *
  9 * All rights reserved.
 10 *
 11 * This program is free software; you can redistribute it and/or modify
 12 * it under the terms of the GNU General Public License as published by
 13 * the Free Software Foundation; either version 2 of the License, or (at
 14 * your option) any later version.
 15 *
 16 * This program is distributed in the hope that it will be useful, but
 17 * WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 19 * NON INFRINGEMENT.  See the GNU General Public License for more
 20 * details.
 21 *
 22 * You should have received a copy of the GNU General Public License
 23 * along with this program; if not, write to the Free Software
 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 25 *
 26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
 27 *
 28 */
 29
 30#include <linux/module.h>
 31#include <linux/kernel.h>
 32#include <linux/types.h>
 33#include <linux/pci.h>
 34#include "../pci.h"
 35#include "shpchp.h"
 36
 37int __ref shpchp_configure_device(struct slot *p_slot)
 38{
 39	struct pci_dev *dev;
 40	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
 41	int num, fn;
 42	struct controller *ctrl = p_slot->ctrl;
 
 
 
 
 
 43
 44	dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
 45	if (dev) {
 46		ctrl_err(ctrl, "Device %s already exists "
 47			 "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev),
 48			 pci_domain_nr(parent), p_slot->bus, p_slot->device);
 49		pci_dev_put(dev);
 50		return -EINVAL;
 
 51	}
 52
 53	num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
 54	if (num == 0) {
 55		ctrl_err(ctrl, "No new device found\n");
 56		return -ENODEV;
 
 57	}
 58
 59	for (fn = 0; fn < 8; fn++) {
 60		dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
 61		if (!dev)
 62			continue;
 63		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
 64				(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) {
 65			/* Find an unused bus number for the new bridge */
 66			struct pci_bus *child;
 67			unsigned char busnr, start = parent->secondary;
 68			unsigned char end = parent->subordinate;
 69			for (busnr = start; busnr <= end; busnr++) {
 70				if (!pci_find_bus(pci_domain_nr(parent),
 71							busnr))
 72					break;
 73			}
 74			if (busnr > end) {
 75				ctrl_err(ctrl,
 76					 "No free bus for hot-added bridge\n");
 77				pci_dev_put(dev);
 78				continue;
 79			}
 80			child = pci_add_new_bus(parent, dev, busnr);
 81			if (!child) {
 82				ctrl_err(ctrl, "Cannot add new bus for %s\n",
 83					 pci_name(dev));
 84				pci_dev_put(dev);
 85				continue;
 86			}
 87			child->subordinate = pci_do_scan_bus(child);
 88			pci_bus_size_bridges(child);
 89		}
 90		pci_configure_slot(dev);
 91		pci_dev_put(dev);
 92	}
 93
 94	pci_bus_assign_resources(parent);
 95	pci_bus_add_devices(parent);
 96	pci_enable_bridges(parent);
 97	return 0;
 
 
 98}
 99
100int shpchp_unconfigure_device(struct slot *p_slot)
101{
102	int rc = 0;
103	int j;
104	u8 bctl = 0;
105	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
 
106	struct controller *ctrl = p_slot->ctrl;
107
108	ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
109		 __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
110
111	for (j = 0; j < 8 ; j++) {
112		struct pci_dev *temp = pci_get_slot(parent,
113				(p_slot->device << 3) | j);
114		if (!temp)
115			continue;
116		if (temp->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
117			pci_read_config_byte(temp, PCI_BRIDGE_CONTROL, &bctl);
 
 
118			if (bctl & PCI_BRIDGE_CTL_VGA) {
119				ctrl_err(ctrl,
120					 "Cannot remove display device %s\n",
121					 pci_name(temp));
122				pci_dev_put(temp);
123				rc = -EINVAL;
124				break;
125			}
126		}
127		pci_stop_and_remove_bus_device(temp);
128		pci_dev_put(temp);
129	}
 
 
130	return rc;
131}
132
v3.15
  1/*
  2 * Standard Hot Plug Controller Driver
  3 *
  4 * Copyright (C) 1995,2001 Compaq Computer Corporation
  5 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
  6 * Copyright (C) 2001 IBM Corp.
  7 * Copyright (C) 2003-2004 Intel Corporation
  8 *
  9 * All rights reserved.
 10 *
 11 * This program is free software; you can redistribute it and/or modify
 12 * it under the terms of the GNU General Public License as published by
 13 * the Free Software Foundation; either version 2 of the License, or (at
 14 * your option) any later version.
 15 *
 16 * This program is distributed in the hope that it will be useful, but
 17 * WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 19 * NON INFRINGEMENT.  See the GNU General Public License for more
 20 * details.
 21 *
 22 * You should have received a copy of the GNU General Public License
 23 * along with this program; if not, write to the Free Software
 24 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 25 *
 26 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
 27 *
 28 */
 29
 30#include <linux/module.h>
 31#include <linux/kernel.h>
 32#include <linux/types.h>
 33#include <linux/pci.h>
 34#include "../pci.h"
 35#include "shpchp.h"
 36
 37int __ref shpchp_configure_device(struct slot *p_slot)
 38{
 39	struct pci_dev *dev;
 
 
 40	struct controller *ctrl = p_slot->ctrl;
 41	struct pci_dev *bridge = ctrl->pci_dev;
 42	struct pci_bus *parent = bridge->subordinate;
 43	int num, ret = 0;
 44
 45	pci_lock_rescan_remove();
 46
 47	dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
 48	if (dev) {
 49		ctrl_err(ctrl, "Device %s already exists "
 50			 "at %04x:%02x:%02x, cannot hot-add\n", pci_name(dev),
 51			 pci_domain_nr(parent), p_slot->bus, p_slot->device);
 52		pci_dev_put(dev);
 53		ret = -EINVAL;
 54		goto out;
 55	}
 56
 57	num = pci_scan_slot(parent, PCI_DEVFN(p_slot->device, 0));
 58	if (num == 0) {
 59		ctrl_err(ctrl, "No new device found\n");
 60		ret = -ENODEV;
 61		goto out;
 62	}
 63
 64	list_for_each_entry(dev, &parent->devices, bus_list) {
 65		if (PCI_SLOT(dev->devfn) != p_slot->device)
 
 66			continue;
 67		if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
 68		    (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
 69			pci_hp_add_bridge(dev);
 70	}
 71
 72	pci_assign_unassigned_bridge_resources(bridge);
 73
 74	list_for_each_entry(dev, &parent->devices, bus_list) {
 75		if (PCI_SLOT(dev->devfn) != p_slot->device)
 76			continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 77		pci_configure_slot(dev);
 
 78	}
 79
 
 80	pci_bus_add_devices(parent);
 81
 82 out:
 83	pci_unlock_rescan_remove();
 84	return ret;
 85}
 86
 87int shpchp_unconfigure_device(struct slot *p_slot)
 88{
 89	int rc = 0;
 
 90	u8 bctl = 0;
 91	struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
 92	struct pci_dev *dev, *temp;
 93	struct controller *ctrl = p_slot->ctrl;
 94
 95	ctrl_dbg(ctrl, "%s: domain:bus:dev = %04x:%02x:%02x\n",
 96		 __func__, pci_domain_nr(parent), p_slot->bus, p_slot->device);
 97
 98	pci_lock_rescan_remove();
 99
100	list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
101		if (PCI_SLOT(dev->devfn) != p_slot->device)
102			continue;
103
104		pci_dev_get(dev);
105		if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
106			pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);
107			if (bctl & PCI_BRIDGE_CTL_VGA) {
108				ctrl_err(ctrl,
109					 "Cannot remove display device %s\n",
110					 pci_name(dev));
111				pci_dev_put(dev);
112				rc = -EINVAL;
113				break;
114			}
115		}
116		pci_stop_and_remove_bus_device(dev);
117		pci_dev_put(dev);
118	}
119
120	pci_unlock_rescan_remove();
121	return rc;
122}
123