aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpi_ipmi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpi_ipmi.c')
-rw-r--r--drivers/acpi/acpi_ipmi.c81
1 files changed, 34 insertions, 47 deletions
diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c
index b285386eb37f..7ec4cd1e7245 100644
--- a/drivers/acpi/acpi_ipmi.c
+++ b/drivers/acpi/acpi_ipmi.c
@@ -46,7 +46,6 @@ MODULE_AUTHOR("Zhao Yakui");
46MODULE_DESCRIPTION("ACPI IPMI Opregion driver"); 46MODULE_DESCRIPTION("ACPI IPMI Opregion driver");
47MODULE_LICENSE("GPL"); 47MODULE_LICENSE("GPL");
48 48
49#define IPMI_FLAGS_HANDLER_INSTALL 0
50 49
51#define ACPI_IPMI_OK 0 50#define ACPI_IPMI_OK 0
52#define ACPI_IPMI_TIMEOUT 0x10 51#define ACPI_IPMI_TIMEOUT 0x10
@@ -66,7 +65,6 @@ struct acpi_ipmi_device {
66 ipmi_user_t user_interface; 65 ipmi_user_t user_interface;
67 int ipmi_ifnum; /* IPMI interface number */ 66 int ipmi_ifnum; /* IPMI interface number */
68 long curr_msgid; 67 long curr_msgid;
69 unsigned long flags;
70 struct ipmi_smi_info smi_data; 68 struct ipmi_smi_info smi_data;
71 bool dead; 69 bool dead;
72 struct kref kref; 70 struct kref kref;
@@ -77,6 +75,14 @@ struct ipmi_driver_data {
77 struct ipmi_smi_watcher bmc_events; 75 struct ipmi_smi_watcher bmc_events;
78 struct ipmi_user_hndl ipmi_hndlrs; 76 struct ipmi_user_hndl ipmi_hndlrs;
79 struct mutex ipmi_lock; 77 struct mutex ipmi_lock;
78 /*
79 * NOTE: IPMI System Interface Selection
80 * There is no system interface specified by the IPMI operation
81 * region access. We try to select one system interface with ACPI
82 * handle set. IPMI messages passed from the ACPI codes are sent
83 * to this selected global IPMI system interface.
84 */
85 struct acpi_ipmi_device *selected_smi;
80}; 86};
81 87
82struct acpi_ipmi_msg { 88struct acpi_ipmi_msg {
@@ -110,8 +116,6 @@ struct acpi_ipmi_buffer {
110static void ipmi_register_bmc(int iface, struct device *dev); 116static void ipmi_register_bmc(int iface, struct device *dev);
111static void ipmi_bmc_gone(int iface); 117static void ipmi_bmc_gone(int iface);
112static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); 118static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data);
113static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi);
114static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi);
115 119
116static struct ipmi_driver_data driver_data = { 120static struct ipmi_driver_data driver_data = {
117 .ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices), 121 .ipmi_devices = LIST_HEAD_INIT(driver_data.ipmi_devices),
@@ -154,14 +158,12 @@ ipmi_dev_alloc(int iface, struct ipmi_smi_info *smi_data, acpi_handle handle)
154 return NULL; 158 return NULL;
155 } 159 }
156 ipmi_device->user_interface = user; 160 ipmi_device->user_interface = user;
157 ipmi_install_space_handler(ipmi_device);
158 161
159 return ipmi_device; 162 return ipmi_device;
160} 163}
161 164
162static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device) 165static void ipmi_dev_release(struct acpi_ipmi_device *ipmi_device)
163{ 166{
164 ipmi_remove_space_handler(ipmi_device);
165 ipmi_destroy_user(ipmi_device->user_interface); 167 ipmi_destroy_user(ipmi_device->user_interface);
166 put_device(ipmi_device->smi_data.dev); 168 put_device(ipmi_device->smi_data.dev);
167 kfree(ipmi_device); 169 kfree(ipmi_device);
@@ -178,6 +180,8 @@ static void ipmi_dev_release_kref(struct kref *kref)
178static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device) 180static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device)
179{ 181{
180 list_del(&ipmi_device->head); 182 list_del(&ipmi_device->head);
183 if (driver_data.selected_smi == ipmi_device)
184 driver_data.selected_smi = NULL;
181 /* 185 /*
182 * Always setting dead flag after deleting from the list or 186 * Always setting dead flag after deleting from the list or
183 * list_for_each_entry() codes must get changed. 187 * list_for_each_entry() codes must get changed.
@@ -185,17 +189,14 @@ static void __ipmi_dev_kill(struct acpi_ipmi_device *ipmi_device)
185 ipmi_device->dead = true; 189 ipmi_device->dead = true;
186} 190}
187 191
188static struct acpi_ipmi_device *acpi_ipmi_dev_get(int iface) 192static struct acpi_ipmi_device *acpi_ipmi_dev_get(void)
189{ 193{
190 struct acpi_ipmi_device *temp, *ipmi_device = NULL; 194 struct acpi_ipmi_device *ipmi_device = NULL;
191 195
192 mutex_lock(&driver_data.ipmi_lock); 196 mutex_lock(&driver_data.ipmi_lock);
193 list_for_each_entry(temp, &driver_data.ipmi_devices, head) { 197 if (driver_data.selected_smi) {
194 if (temp->ipmi_ifnum == iface) { 198 ipmi_device = driver_data.selected_smi;
195 ipmi_device = temp; 199 kref_get(&ipmi_device->kref);
196 kref_get(&ipmi_device->kref);
197 break;
198 }
199 } 200 }
200 mutex_unlock(&driver_data.ipmi_lock); 201 mutex_unlock(&driver_data.ipmi_lock);
201 202
@@ -416,6 +417,8 @@ static void ipmi_register_bmc(int iface, struct device *dev)
416 goto err_lock; 417 goto err_lock;
417 } 418 }
418 419
420 if (!driver_data.selected_smi)
421 driver_data.selected_smi = ipmi_device;
419 list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices); 422 list_add_tail(&ipmi_device->head, &driver_data.ipmi_devices);
420 mutex_unlock(&driver_data.ipmi_lock); 423 mutex_unlock(&driver_data.ipmi_lock);
421 put_device(smi_data.dev); 424 put_device(smi_data.dev);
@@ -443,6 +446,10 @@ static void ipmi_bmc_gone(int iface)
443 break; 446 break;
444 } 447 }
445 } 448 }
449 if (!driver_data.selected_smi)
450 driver_data.selected_smi = list_first_entry_or_null(
451 &driver_data.ipmi_devices,
452 struct acpi_ipmi_device, head);
446 mutex_unlock(&driver_data.ipmi_lock); 453 mutex_unlock(&driver_data.ipmi_lock);
447 if (dev_found) { 454 if (dev_found) {
448 ipmi_flush_tx_msg(ipmi_device); 455 ipmi_flush_tx_msg(ipmi_device);
@@ -471,7 +478,6 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
471 void *handler_context, void *region_context) 478 void *handler_context, void *region_context)
472{ 479{
473 struct acpi_ipmi_msg *tx_msg; 480 struct acpi_ipmi_msg *tx_msg;
474 int iface = (long)handler_context;
475 struct acpi_ipmi_device *ipmi_device; 481 struct acpi_ipmi_device *ipmi_device;
476 int err; 482 int err;
477 acpi_status status; 483 acpi_status status;
@@ -485,7 +491,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,
485 if ((function & ACPI_IO_MASK) == ACPI_READ) 491 if ((function & ACPI_IO_MASK) == ACPI_READ)
486 return AE_TYPE; 492 return AE_TYPE;
487 493
488 ipmi_device = acpi_ipmi_dev_get(iface); 494 ipmi_device = acpi_ipmi_dev_get();
489 if (!ipmi_device) 495 if (!ipmi_device)
490 return AE_NOT_EXIST; 496 return AE_NOT_EXIST;
491 497
@@ -534,47 +540,26 @@ out_ref:
534 return status; 540 return status;
535} 541}
536 542
537static void ipmi_remove_space_handler(struct acpi_ipmi_device *ipmi)
538{
539 if (!test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
540 return;
541
542 acpi_remove_address_space_handler(ipmi->handle,
543 ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler);
544
545 clear_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
546}
547
548static int ipmi_install_space_handler(struct acpi_ipmi_device *ipmi)
549{
550 acpi_status status;
551
552 if (test_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags))
553 return 0;
554
555 status = acpi_install_address_space_handler(ipmi->handle,
556 ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler,
557 NULL, (void *)((long)ipmi->ipmi_ifnum));
558 if (ACPI_FAILURE(status)) {
559 struct pnp_dev *pnp_dev = ipmi->pnp_dev;
560 dev_warn(&pnp_dev->dev, "Can't register IPMI opregion space "
561 "handle\n");
562 return -EINVAL;
563 }
564 set_bit(IPMI_FLAGS_HANDLER_INSTALL, &ipmi->flags);
565 return 0;
566}
567
568static int __init acpi_ipmi_init(void) 543static int __init acpi_ipmi_init(void)
569{ 544{
570 int result = 0; 545 int result = 0;
546 acpi_status status;
571 547
572 if (acpi_disabled) 548 if (acpi_disabled)
573 return result; 549 return result;
574 550
575 mutex_init(&driver_data.ipmi_lock); 551 mutex_init(&driver_data.ipmi_lock);
576 552
553 status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
554 ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler,
555 NULL, NULL);
556 if (ACPI_FAILURE(status)) {
557 pr_warn("Can't register IPMI opregion space handle\n");
558 return -EINVAL;
559 }
577 result = ipmi_smi_watcher_register(&driver_data.bmc_events); 560 result = ipmi_smi_watcher_register(&driver_data.bmc_events);
561 if (result)
562 pr_err("Can't register IPMI system interface watcher\n");
578 563
579 return result; 564 return result;
580} 565}
@@ -608,6 +593,8 @@ static void __exit acpi_ipmi_exit(void)
608 mutex_lock(&driver_data.ipmi_lock); 593 mutex_lock(&driver_data.ipmi_lock);
609 } 594 }
610 mutex_unlock(&driver_data.ipmi_lock); 595 mutex_unlock(&driver_data.ipmi_lock);
596 acpi_remove_address_space_handler(ACPI_ROOT_OBJECT,
597 ACPI_ADR_SPACE_IPMI, &acpi_ipmi_space_handler);
611} 598}
612 599
613module_init(acpi_ipmi_init); 600module_init(acpi_ipmi_init);