root / hw / pci / pci-hotplug-old.c @ bf0da4df
History | View | Annotate | Download (9.9 kB)
1 | 6f338c34 | aliguori | /*
|
---|---|---|---|
2 | 79ca616f | David Gibson | * Deprecated PCI hotplug interface support
|
3 | 79ca616f | David Gibson | * This covers the old pci_add / pci_del command, whereas the more general
|
4 | 79ca616f | David Gibson | * device_add / device_del commands are now preferred.
|
5 | 6f338c34 | aliguori | *
|
6 | 6f338c34 | aliguori | * Copyright (c) 2004 Fabrice Bellard
|
7 | 6f338c34 | aliguori | *
|
8 | 6f338c34 | aliguori | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
9 | 6f338c34 | aliguori | * of this software and associated documentation files (the "Software"), to deal
|
10 | 6f338c34 | aliguori | * in the Software without restriction, including without limitation the rights
|
11 | 6f338c34 | aliguori | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12 | 6f338c34 | aliguori | * copies of the Software, and to permit persons to whom the Software is
|
13 | 6f338c34 | aliguori | * furnished to do so, subject to the following conditions:
|
14 | 6f338c34 | aliguori | *
|
15 | 6f338c34 | aliguori | * The above copyright notice and this permission notice shall be included in
|
16 | 6f338c34 | aliguori | * all copies or substantial portions of the Software.
|
17 | 6f338c34 | aliguori | *
|
18 | 6f338c34 | aliguori | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19 | 6f338c34 | aliguori | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20 | 6f338c34 | aliguori | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
21 | 6f338c34 | aliguori | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22 | 6f338c34 | aliguori | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23 | 6f338c34 | aliguori | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24 | 6f338c34 | aliguori | * THE SOFTWARE.
|
25 | 6f338c34 | aliguori | */
|
26 | 6f338c34 | aliguori | |
27 | c759b24f | Michael S. Tsirkin | #include "hw/hw.h" |
28 | c759b24f | Michael S. Tsirkin | #include "hw/boards.h" |
29 | c759b24f | Michael S. Tsirkin | #include "hw/pci/pci.h" |
30 | 1422e32d | Paolo Bonzini | #include "net/net.h" |
31 | 0d09e41a | Paolo Bonzini | #include "hw/i386/pc.h" |
32 | 83c9089e | Paolo Bonzini | #include "monitor/monitor.h" |
33 | 0d09e41a | Paolo Bonzini | #include "hw/scsi/scsi.h" |
34 | 0d09e41a | Paolo Bonzini | #include "hw/virtio/virtio-blk.h" |
35 | 1de7afc9 | Paolo Bonzini | #include "qemu/config-file.h" |
36 | 9c17d615 | Paolo Bonzini | #include "sysemu/blockdev.h" |
37 | 7b1b5d19 | Paolo Bonzini | #include "qapi/error.h" |
38 | 6f338c34 | aliguori | |
39 | 1ef7a2a2 | David Gibson | static int pci_read_devaddr(Monitor *mon, const char *addr, |
40 | 6ac363b5 | David Gibson | int *busp, unsigned *slotp) |
41 | 6ac363b5 | David Gibson | { |
42 | 1ef7a2a2 | David Gibson | int dom;
|
43 | 1ef7a2a2 | David Gibson | |
44 | 6ac363b5 | David Gibson | /* strip legacy tag */
|
45 | 6ac363b5 | David Gibson | if (!strncmp(addr, "pci_addr=", 9)) { |
46 | 6ac363b5 | David Gibson | addr += 9;
|
47 | 6ac363b5 | David Gibson | } |
48 | 1ef7a2a2 | David Gibson | if (pci_parse_devaddr(addr, &dom, busp, slotp, NULL)) { |
49 | 6ac363b5 | David Gibson | monitor_printf(mon, "Invalid pci address\n");
|
50 | 6ac363b5 | David Gibson | return -1; |
51 | 6ac363b5 | David Gibson | } |
52 | 1ef7a2a2 | David Gibson | if (dom != 0) { |
53 | 1ef7a2a2 | David Gibson | monitor_printf(mon, "Multiple PCI domains not supported, use device_add\n");
|
54 | 1ef7a2a2 | David Gibson | return -1; |
55 | 1ef7a2a2 | David Gibson | } |
56 | 6ac363b5 | David Gibson | return 0; |
57 | 6ac363b5 | David Gibson | } |
58 | 6ac363b5 | David Gibson | |
59 | 1f5f6638 | Markus Armbruster | static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
|
60 | c59c7ea9 | Mark McLoughlin | const char *devaddr, |
61 | c59c7ea9 | Mark McLoughlin | const char *opts_str) |
62 | 6f338c34 | aliguori | { |
63 | 4559a1db | Luiz Capitulino | Error *local_err = NULL;
|
64 | c59c7ea9 | Mark McLoughlin | QemuOpts *opts; |
65 | 9bc47305 | David Gibson | PCIBus *root = pci_find_primary_bus(); |
66 | 53e0d8af | Gerd Hoffmann | PCIBus *bus; |
67 | 53e0d8af | Gerd Hoffmann | int ret, devfn;
|
68 | 53e0d8af | Gerd Hoffmann | |
69 | 9bc47305 | David Gibson | if (!root) {
|
70 | 9bc47305 | David Gibson | monitor_printf(mon, "no primary PCI bus (if there are multiple"
|
71 | 9bc47305 | David Gibson | " PCI roots, you must use device_add instead)");
|
72 | 9bc47305 | David Gibson | return NULL; |
73 | 9bc47305 | David Gibson | } |
74 | 9bc47305 | David Gibson | |
75 | 9bc47305 | David Gibson | bus = pci_get_bus_devfn(&devfn, root, devaddr); |
76 | 53e0d8af | Gerd Hoffmann | if (!bus) {
|
77 | 53e0d8af | Gerd Hoffmann | monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
|
78 | 53e0d8af | Gerd Hoffmann | return NULL; |
79 | 53e0d8af | Gerd Hoffmann | } |
80 | 53e0d8af | Gerd Hoffmann | if (!((BusState*)bus)->allow_hotplug) {
|
81 | 53e0d8af | Gerd Hoffmann | monitor_printf(mon, "PCI bus doesn't support hotplug\n");
|
82 | 53e0d8af | Gerd Hoffmann | return NULL; |
83 | 53e0d8af | Gerd Hoffmann | } |
84 | 6f338c34 | aliguori | |
85 | 3329f07b | Gerd Hoffmann | opts = qemu_opts_parse(qemu_find_opts("net"), opts_str ? opts_str : "", 0); |
86 | c59c7ea9 | Mark McLoughlin | if (!opts) {
|
87 | c59c7ea9 | Mark McLoughlin | return NULL; |
88 | c59c7ea9 | Mark McLoughlin | } |
89 | c59c7ea9 | Mark McLoughlin | |
90 | c59c7ea9 | Mark McLoughlin | qemu_opt_set(opts, "type", "nic"); |
91 | c59c7ea9 | Mark McLoughlin | |
92 | 4559a1db | Luiz Capitulino | ret = net_client_init(opts, 0, &local_err);
|
93 | 4559a1db | Luiz Capitulino | if (error_is_set(&local_err)) {
|
94 | 4559a1db | Luiz Capitulino | qerror_report_err(local_err); |
95 | 4559a1db | Luiz Capitulino | error_free(local_err); |
96 | 6f338c34 | aliguori | return NULL; |
97 | 4559a1db | Luiz Capitulino | } |
98 | 5607c388 | Markus Armbruster | if (nd_table[ret].devaddr) {
|
99 | 5607c388 | Markus Armbruster | monitor_printf(mon, "Parameter addr not supported\n");
|
100 | 5607c388 | Markus Armbruster | return NULL; |
101 | 5607c388 | Markus Armbruster | } |
102 | 9bc47305 | David Gibson | return pci_nic_init(&nd_table[ret], root, "rtl8139", devaddr); |
103 | 6f338c34 | aliguori | } |
104 | 6f338c34 | aliguori | |
105 | 6fdb03d5 | Markus Armbruster | static int scsi_hot_add(Monitor *mon, DeviceState *adapter, |
106 | 6fdb03d5 | Markus Armbruster | DriveInfo *dinfo, int printinfo)
|
107 | 30d335d6 | Gerd Hoffmann | { |
108 | 30d335d6 | Gerd Hoffmann | SCSIBus *scsibus; |
109 | 30d335d6 | Gerd Hoffmann | SCSIDevice *scsidev; |
110 | 30d335d6 | Gerd Hoffmann | |
111 | b5007bcc | Paolo Bonzini | scsibus = (SCSIBus *) |
112 | b5007bcc | Paolo Bonzini | object_dynamic_cast(OBJECT(QLIST_FIRST(&adapter->child_bus)), |
113 | b5007bcc | Paolo Bonzini | TYPE_SCSI_BUS); |
114 | b5007bcc | Paolo Bonzini | if (!scsibus) {
|
115 | b5007bcc | Paolo Bonzini | error_report("Device is not a SCSI adapter");
|
116 | b5007bcc | Paolo Bonzini | return -1; |
117 | b5007bcc | Paolo Bonzini | } |
118 | 30d335d6 | Gerd Hoffmann | |
119 | 30d335d6 | Gerd Hoffmann | /*
|
120 | 30d335d6 | Gerd Hoffmann | * drive_init() tries to find a default for dinfo->unit. Doesn't
|
121 | 30d335d6 | Gerd Hoffmann | * work at all for hotplug though as we assign the device to a
|
122 | 30d335d6 | Gerd Hoffmann | * specific bus instead of the first bus with spare scsi ids.
|
123 | 30d335d6 | Gerd Hoffmann | *
|
124 | 30d335d6 | Gerd Hoffmann | * Ditch the calculated value and reload from option string (if
|
125 | 30d335d6 | Gerd Hoffmann | * specified).
|
126 | 30d335d6 | Gerd Hoffmann | */
|
127 | 30d335d6 | Gerd Hoffmann | dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); |
128 | 31e1ea3e | Markus Armbruster | dinfo->bus = scsibus->busnr; |
129 | ce4e7e46 | Paolo Bonzini | scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, |
130 | caad4eb3 | Andreas Färber | false, -1, NULL, NULL); |
131 | fa66b909 | Markus Armbruster | if (!scsidev) {
|
132 | fa66b909 | Markus Armbruster | return -1; |
133 | fa66b909 | Markus Armbruster | } |
134 | 11f4d7f4 | Gerd Hoffmann | dinfo->unit = scsidev->id; |
135 | 30d335d6 | Gerd Hoffmann | |
136 | 30d335d6 | Gerd Hoffmann | if (printinfo)
|
137 | 6fdb03d5 | Markus Armbruster | monitor_printf(mon, "OK bus %d, unit %d\n",
|
138 | 6fdb03d5 | Markus Armbruster | scsibus->busnr, scsidev->id); |
139 | 30d335d6 | Gerd Hoffmann | return 0; |
140 | 30d335d6 | Gerd Hoffmann | } |
141 | 30d335d6 | Gerd Hoffmann | |
142 | 4dbd84e2 | Markus Armbruster | int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo) |
143 | 6f338c34 | aliguori | { |
144 | 1ef7a2a2 | David Gibson | int pci_bus;
|
145 | 6f338c34 | aliguori | unsigned slot;
|
146 | 1ef7a2a2 | David Gibson | PCIBus *root = pci_find_primary_bus(); |
147 | 6f338c34 | aliguori | PCIDevice *dev; |
148 | f18c16de | Luiz Capitulino | const char *pci_addr = qdict_get_str(qdict, "pci_addr"); |
149 | 6f338c34 | aliguori | |
150 | 4dbd84e2 | Markus Armbruster | switch (dinfo->type) {
|
151 | 6f338c34 | aliguori | case IF_SCSI:
|
152 | 1ef7a2a2 | David Gibson | if (!root) {
|
153 | 9bc47305 | David Gibson | monitor_printf(mon, "no primary PCI bus (if there are multiple"
|
154 | 9bc47305 | David Gibson | " PCI roots, you must use device_add instead)");
|
155 | 1ef7a2a2 | David Gibson | goto err;
|
156 | 1ef7a2a2 | David Gibson | } |
157 | 1ef7a2a2 | David Gibson | if (pci_read_devaddr(mon, pci_addr, &pci_bus, &slot)) {
|
158 | 4db49dc0 | Gerd Hoffmann | goto err;
|
159 | 4db49dc0 | Gerd Hoffmann | } |
160 | 1ef7a2a2 | David Gibson | dev = pci_find_device(root, pci_bus, PCI_DEVFN(slot, 0));
|
161 | 4db49dc0 | Gerd Hoffmann | if (!dev) {
|
162 | 4db49dc0 | Gerd Hoffmann | monitor_printf(mon, "no pci device with address %s\n", pci_addr);
|
163 | 4db49dc0 | Gerd Hoffmann | goto err;
|
164 | 4db49dc0 | Gerd Hoffmann | } |
165 | 6fdb03d5 | Markus Armbruster | if (scsi_hot_add(mon, &dev->qdev, dinfo, 1) != 0) { |
166 | 30d335d6 | Gerd Hoffmann | goto err;
|
167 | 30d335d6 | Gerd Hoffmann | } |
168 | 6f338c34 | aliguori | break;
|
169 | 6f338c34 | aliguori | default:
|
170 | 4dbd84e2 | Markus Armbruster | monitor_printf(mon, "Can't hot-add drive to type %d\n", dinfo->type);
|
171 | 4db49dc0 | Gerd Hoffmann | goto err;
|
172 | 6f338c34 | aliguori | } |
173 | 6f338c34 | aliguori | |
174 | dd97aa8a | Alexander Graf | return 0; |
175 | 4db49dc0 | Gerd Hoffmann | err:
|
176 | dd97aa8a | Alexander Graf | return -1; |
177 | 6f338c34 | aliguori | } |
178 | 6f338c34 | aliguori | |
179 | 1f5f6638 | Markus Armbruster | static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
|
180 | 1f5f6638 | Markus Armbruster | const char *devaddr, |
181 | 376253ec | aliguori | const char *opts) |
182 | 6f338c34 | aliguori | { |
183 | 1f5f6638 | Markus Armbruster | PCIDevice *dev; |
184 | 06c79f4e | Sebastian Herbszt | DriveInfo *dinfo = NULL;
|
185 | 751c6a17 | Gerd Hoffmann | int type = -1; |
186 | 6f338c34 | aliguori | char buf[128]; |
187 | 9bc47305 | David Gibson | PCIBus *root = pci_find_primary_bus(); |
188 | 49bd1458 | Markus Armbruster | PCIBus *bus; |
189 | 49bd1458 | Markus Armbruster | int devfn;
|
190 | 6f338c34 | aliguori | |
191 | 6f338c34 | aliguori | if (get_param_value(buf, sizeof(buf), "if", opts)) { |
192 | 6f338c34 | aliguori | if (!strcmp(buf, "scsi")) |
193 | 6f338c34 | aliguori | type = IF_SCSI; |
194 | 6f338c34 | aliguori | else if (!strcmp(buf, "virtio")) { |
195 | 6f338c34 | aliguori | type = IF_VIRTIO; |
196 | 8707ecca | aliguori | } else {
|
197 | 8707ecca | aliguori | monitor_printf(mon, "type %s not a hotpluggable PCI device.\n", buf);
|
198 | 1f5f6638 | Markus Armbruster | return NULL; |
199 | 6f338c34 | aliguori | } |
200 | 6f338c34 | aliguori | } else {
|
201 | 376253ec | aliguori | monitor_printf(mon, "no if= specified\n");
|
202 | 1f5f6638 | Markus Armbruster | return NULL; |
203 | 6f338c34 | aliguori | } |
204 | 6f338c34 | aliguori | |
205 | 6f338c34 | aliguori | if (get_param_value(buf, sizeof(buf), "file", opts)) { |
206 | 751c6a17 | Gerd Hoffmann | dinfo = add_init_drive(opts); |
207 | 751c6a17 | Gerd Hoffmann | if (!dinfo)
|
208 | 1f5f6638 | Markus Armbruster | return NULL; |
209 | 751c6a17 | Gerd Hoffmann | if (dinfo->devaddr) {
|
210 | c2cc47a4 | Markus Armbruster | monitor_printf(mon, "Parameter addr not supported\n");
|
211 | c2cc47a4 | Markus Armbruster | return NULL; |
212 | c2cc47a4 | Markus Armbruster | } |
213 | 7432ff5d | Blue Swirl | } else {
|
214 | 7432ff5d | Blue Swirl | dinfo = NULL;
|
215 | 6f338c34 | aliguori | } |
216 | 6f338c34 | aliguori | |
217 | 9bc47305 | David Gibson | if (!root) {
|
218 | 9bc47305 | David Gibson | monitor_printf(mon, "no primary PCI bus (if there are multiple"
|
219 | 9bc47305 | David Gibson | " PCI roots, you must use device_add instead)");
|
220 | 9bc47305 | David Gibson | return NULL; |
221 | 9bc47305 | David Gibson | } |
222 | 9bc47305 | David Gibson | bus = pci_get_bus_devfn(&devfn, root, devaddr); |
223 | 49bd1458 | Markus Armbruster | if (!bus) {
|
224 | 49bd1458 | Markus Armbruster | monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
|
225 | 49bd1458 | Markus Armbruster | return NULL; |
226 | 49bd1458 | Markus Armbruster | } |
227 | 53e0d8af | Gerd Hoffmann | if (!((BusState*)bus)->allow_hotplug) {
|
228 | 53e0d8af | Gerd Hoffmann | monitor_printf(mon, "PCI bus doesn't support hotplug\n");
|
229 | 53e0d8af | Gerd Hoffmann | return NULL; |
230 | 53e0d8af | Gerd Hoffmann | } |
231 | 49bd1458 | Markus Armbruster | |
232 | 6f338c34 | aliguori | switch (type) {
|
233 | 6f338c34 | aliguori | case IF_SCSI:
|
234 | 499cf102 | Markus Armbruster | dev = pci_create(bus, devfn, "lsi53c895a");
|
235 | 5b684b5a | Gerd Hoffmann | if (qdev_init(&dev->qdev) < 0) |
236 | 5b684b5a | Gerd Hoffmann | dev = NULL;
|
237 | ec7efac4 | Daniel P. Berrange | if (dev && dinfo) {
|
238 | 6fdb03d5 | Markus Armbruster | if (scsi_hot_add(mon, &dev->qdev, dinfo, 0) != 0) { |
239 | 56f9107e | Luiz Capitulino | qdev_unplug(&dev->qdev, NULL);
|
240 | 30d335d6 | Gerd Hoffmann | dev = NULL;
|
241 | 30d335d6 | Gerd Hoffmann | } |
242 | 5b684b5a | Gerd Hoffmann | } |
243 | 6f338c34 | aliguori | break;
|
244 | 6f338c34 | aliguori | case IF_VIRTIO:
|
245 | 7432ff5d | Blue Swirl | if (!dinfo) {
|
246 | 7432ff5d | Blue Swirl | monitor_printf(mon, "virtio requires a backing file/device.\n");
|
247 | 7432ff5d | Blue Swirl | return NULL; |
248 | 7432ff5d | Blue Swirl | } |
249 | 499cf102 | Markus Armbruster | dev = pci_create(bus, devfn, "virtio-blk-pci");
|
250 | 18846dee | Markus Armbruster | if (qdev_prop_set_drive(&dev->qdev, "drive", dinfo->bdrv) < 0) { |
251 | 18846dee | Markus Armbruster | qdev_free(&dev->qdev); |
252 | 18846dee | Markus Armbruster | dev = NULL;
|
253 | 18846dee | Markus Armbruster | break;
|
254 | 18846dee | Markus Armbruster | } |
255 | 5b684b5a | Gerd Hoffmann | if (qdev_init(&dev->qdev) < 0) |
256 | 5b684b5a | Gerd Hoffmann | dev = NULL;
|
257 | 6f338c34 | aliguori | break;
|
258 | 1f5f6638 | Markus Armbruster | default:
|
259 | 1f5f6638 | Markus Armbruster | dev = NULL;
|
260 | 6f338c34 | aliguori | } |
261 | 1f5f6638 | Markus Armbruster | return dev;
|
262 | 6f338c34 | aliguori | } |
263 | 6f338c34 | aliguori | |
264 | 6c6a58ae | Markus Armbruster | void pci_device_hot_add(Monitor *mon, const QDict *qdict) |
265 | 6f338c34 | aliguori | { |
266 | 6f338c34 | aliguori | PCIDevice *dev = NULL;
|
267 | 1d4daa91 | Luiz Capitulino | const char *pci_addr = qdict_get_str(qdict, "pci_addr"); |
268 | 1d4daa91 | Luiz Capitulino | const char *type = qdict_get_str(qdict, "type"); |
269 | 1d4daa91 | Luiz Capitulino | const char *opts = qdict_get_try_str(qdict, "opts"); |
270 | 6f338c34 | aliguori | |
271 | e9283f8b | Jan Kiszka | /* strip legacy tag */
|
272 | e9283f8b | Jan Kiszka | if (!strncmp(pci_addr, "pci_addr=", 9)) { |
273 | e9283f8b | Jan Kiszka | pci_addr += 9;
|
274 | 6f338c34 | aliguori | } |
275 | 6f338c34 | aliguori | |
276 | a62acdc0 | Jan Kiszka | if (!opts) {
|
277 | a62acdc0 | Jan Kiszka | opts = "";
|
278 | a62acdc0 | Jan Kiszka | } |
279 | a62acdc0 | Jan Kiszka | |
280 | e9283f8b | Jan Kiszka | if (!strcmp(pci_addr, "auto")) |
281 | e9283f8b | Jan Kiszka | pci_addr = NULL;
|
282 | 6f338c34 | aliguori | |
283 | 395560c8 | Luiz Capitulino | if (strcmp(type, "nic") == 0) { |
284 | e9283f8b | Jan Kiszka | dev = qemu_pci_hot_add_nic(mon, pci_addr, opts); |
285 | 395560c8 | Luiz Capitulino | } else if (strcmp(type, "storage") == 0) { |
286 | e9283f8b | Jan Kiszka | dev = qemu_pci_hot_add_storage(mon, pci_addr, opts); |
287 | 395560c8 | Luiz Capitulino | } else {
|
288 | 376253ec | aliguori | monitor_printf(mon, "invalid type: %s\n", type);
|
289 | 395560c8 | Luiz Capitulino | } |
290 | 6f338c34 | aliguori | |
291 | 6f338c34 | aliguori | if (dev) {
|
292 | 568f0690 | David Gibson | monitor_printf(mon, "OK root bus %s, bus %d, slot %d, function %d\n",
|
293 | 568f0690 | David Gibson | pci_root_bus_path(dev), |
294 | e075e788 | Isaku Yamahata | pci_bus_num(dev->bus), PCI_SLOT(dev->devfn), |
295 | 6c6a58ae | Markus Armbruster | PCI_FUNC(dev->devfn)); |
296 | 6c6a58ae | Markus Armbruster | } else
|
297 | 376253ec | aliguori | monitor_printf(mon, "failed to add %s\n", opts);
|
298 | 6f338c34 | aliguori | } |
299 | 6f338c34 | aliguori | |
300 | f2b07c92 | Isaku Yamahata | static int pci_device_hot_remove(Monitor *mon, const char *pci_addr) |
301 | 6f338c34 | aliguori | { |
302 | 1ef7a2a2 | David Gibson | PCIBus *root = pci_find_primary_bus(); |
303 | 6f338c34 | aliguori | PCIDevice *d; |
304 | 1ef7a2a2 | David Gibson | int bus;
|
305 | 6f338c34 | aliguori | unsigned slot;
|
306 | 56f9107e | Luiz Capitulino | Error *local_err = NULL;
|
307 | 6f338c34 | aliguori | |
308 | 1ef7a2a2 | David Gibson | if (!root) {
|
309 | 9bc47305 | David Gibson | monitor_printf(mon, "no primary PCI bus (if there are multiple"
|
310 | 9bc47305 | David Gibson | " PCI roots, you must use device_del instead)");
|
311 | 1ef7a2a2 | David Gibson | return -1; |
312 | 1ef7a2a2 | David Gibson | } |
313 | 1ef7a2a2 | David Gibson | |
314 | 1ef7a2a2 | David Gibson | if (pci_read_devaddr(mon, pci_addr, &bus, &slot)) {
|
315 | 053801bc | Luiz Capitulino | return -1; |
316 | 6f338c34 | aliguori | } |
317 | 6f338c34 | aliguori | |
318 | 1ef7a2a2 | David Gibson | d = pci_find_device(root, bus, PCI_DEVFN(slot, 0));
|
319 | 6f338c34 | aliguori | if (!d) {
|
320 | 376253ec | aliguori | monitor_printf(mon, "slot %d empty\n", slot);
|
321 | 053801bc | Luiz Capitulino | return -1; |
322 | 6f338c34 | aliguori | } |
323 | 56f9107e | Luiz Capitulino | |
324 | 56f9107e | Luiz Capitulino | qdev_unplug(&d->qdev, &local_err); |
325 | 56f9107e | Luiz Capitulino | if (error_is_set(&local_err)) {
|
326 | 56f9107e | Luiz Capitulino | monitor_printf(mon, "%s\n", error_get_pretty(local_err));
|
327 | 56f9107e | Luiz Capitulino | error_free(local_err); |
328 | 56f9107e | Luiz Capitulino | return -1; |
329 | 56f9107e | Luiz Capitulino | } |
330 | 56f9107e | Luiz Capitulino | |
331 | 56f9107e | Luiz Capitulino | return 0; |
332 | 6f338c34 | aliguori | } |
333 | 6f338c34 | aliguori | |
334 | b752daf0 | Markus Armbruster | void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict) |
335 | 38183186 | Luiz Capitulino | { |
336 | b752daf0 | Markus Armbruster | pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr"));
|
337 | 38183186 | Luiz Capitulino | } |