aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/pciehp.h5
-rw-r--r--drivers/pci/hotplug/pciehp_core.c80
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c179
3 files changed, 128 insertions, 136 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 8492fab800cc..d17233ae06f5 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -43,6 +43,7 @@ extern int pciehp_poll_mode;
43extern int pciehp_poll_time; 43extern int pciehp_poll_time;
44extern int pciehp_debug; 44extern int pciehp_debug;
45extern int pciehp_force; 45extern int pciehp_force;
46extern int pciehp_slot_with_bus;
46extern struct workqueue_struct *pciehp_wq; 47extern struct workqueue_struct *pciehp_wq;
47 48
48#define dbg(format, arg...) \ 49#define dbg(format, arg...) \
@@ -156,10 +157,10 @@ extern u8 pciehp_handle_power_fault(struct slot *p_slot);
156extern int pciehp_configure_device(struct slot *p_slot); 157extern int pciehp_configure_device(struct slot *p_slot);
157extern int pciehp_unconfigure_device(struct slot *p_slot); 158extern int pciehp_unconfigure_device(struct slot *p_slot);
158extern void pciehp_queue_pushbutton_work(struct work_struct *work); 159extern void pciehp_queue_pushbutton_work(struct work_struct *work);
159int pcie_init(struct controller *ctrl, struct pcie_device *dev); 160struct controller *pcie_init(struct pcie_device *dev);
160int pciehp_enable_slot(struct slot *p_slot); 161int pciehp_enable_slot(struct slot *p_slot);
161int pciehp_disable_slot(struct slot *p_slot); 162int pciehp_disable_slot(struct slot *p_slot);
162int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev); 163int pcie_enable_notification(struct controller *ctrl);
163 164
164static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device) 165static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
165{ 166{
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 7b21c86e4bff..d0fb56936911 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -41,7 +41,7 @@ int pciehp_debug;
41int pciehp_poll_mode; 41int pciehp_poll_mode;
42int pciehp_poll_time; 42int pciehp_poll_time;
43int pciehp_force; 43int pciehp_force;
44static int pciehp_slot_with_bus; 44int pciehp_slot_with_bus;
45struct workqueue_struct *pciehp_wq; 45struct workqueue_struct *pciehp_wq;
46 46
47#define DRIVER_VERSION "0.4" 47#define DRIVER_VERSION "0.4"
@@ -183,23 +183,10 @@ static struct hotplug_slot_attribute hotplug_slot_attr_lock = {
183 */ 183 */
184static void release_slot(struct hotplug_slot *hotplug_slot) 184static void release_slot(struct hotplug_slot *hotplug_slot)
185{ 185{
186 struct slot *slot = hotplug_slot->private;
187
188 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name); 186 dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
189 187
190 kfree(slot->hotplug_slot->info); 188 kfree(hotplug_slot->info);
191 kfree(slot->hotplug_slot); 189 kfree(hotplug_slot);
192 kfree(slot);
193}
194
195static void make_slot_name(struct slot *slot)
196{
197 if (pciehp_slot_with_bus)
198 snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d",
199 slot->bus, slot->number);
200 else
201 snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d",
202 slot->number);
203} 190}
204 191
205static int init_slots(struct controller *ctrl) 192static int init_slots(struct controller *ctrl)
@@ -208,44 +195,27 @@ static int init_slots(struct controller *ctrl)
208 struct hotplug_slot *hotplug_slot; 195 struct hotplug_slot *hotplug_slot;
209 struct hotplug_slot_info *info; 196 struct hotplug_slot_info *info;
210 int retval = -ENOMEM; 197 int retval = -ENOMEM;
211 int i;
212
213 for (i = 0; i < ctrl->num_slots; i++) {
214 slot = kzalloc(sizeof(*slot), GFP_KERNEL);
215 if (!slot)
216 goto error;
217 198
199 list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
218 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL); 200 hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
219 if (!hotplug_slot) 201 if (!hotplug_slot)
220 goto error_slot; 202 goto error;
221 slot->hotplug_slot = hotplug_slot;
222 203
223 info = kzalloc(sizeof(*info), GFP_KERNEL); 204 info = kzalloc(sizeof(*info), GFP_KERNEL);
224 if (!info) 205 if (!info)
225 goto error_hpslot; 206 goto error_hpslot;
226 hotplug_slot->info = info;
227
228 hotplug_slot->name = slot->name;
229
230 slot->hp_slot = i;
231 slot->ctrl = ctrl;
232 slot->bus = ctrl->pci_dev->subordinate->number;
233 slot->device = ctrl->slot_device_offset + i;
234 slot->hpc_ops = ctrl->hpc_ops;
235 slot->number = ctrl->first_slot;
236 mutex_init(&slot->lock);
237 INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
238 207
239 /* register this slot with the hotplug pci core */ 208 /* register this slot with the hotplug pci core */
209 hotplug_slot->info = info;
210 hotplug_slot->name = slot->name;
240 hotplug_slot->private = slot; 211 hotplug_slot->private = slot;
241 hotplug_slot->release = &release_slot; 212 hotplug_slot->release = &release_slot;
242 make_slot_name(slot);
243 hotplug_slot->ops = &pciehp_hotplug_slot_ops; 213 hotplug_slot->ops = &pciehp_hotplug_slot_ops;
244
245 get_power_status(hotplug_slot, &info->power_status); 214 get_power_status(hotplug_slot, &info->power_status);
246 get_attention_status(hotplug_slot, &info->attention_status); 215 get_attention_status(hotplug_slot, &info->attention_status);
247 get_latch_status(hotplug_slot, &info->latch_status); 216 get_latch_status(hotplug_slot, &info->latch_status);
248 get_adapter_status(hotplug_slot, &info->adapter_status); 217 get_adapter_status(hotplug_slot, &info->adapter_status);
218 slot->hotplug_slot = hotplug_slot;
249 219
250 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " 220 dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x "
251 "slot_device_offset=%x\n", slot->bus, slot->device, 221 "slot_device_offset=%x\n", slot->bus, slot->device,
@@ -271,8 +241,6 @@ static int init_slots(struct controller *ctrl)
271 goto error_info; 241 goto error_info;
272 } 242 }
273 } 243 }
274
275 list_add(&slot->slot_list, &ctrl->slot_list);
276 } 244 }
277 245
278 return 0; 246 return 0;
@@ -280,27 +248,18 @@ error_info:
280 kfree(info); 248 kfree(info);
281error_hpslot: 249error_hpslot:
282 kfree(hotplug_slot); 250 kfree(hotplug_slot);
283error_slot:
284 kfree(slot);
285error: 251error:
286 return retval; 252 return retval;
287} 253}
288 254
289static void cleanup_slots(struct controller *ctrl) 255static void cleanup_slots(struct controller *ctrl)
290{ 256{
291 struct list_head *tmp;
292 struct list_head *next;
293 struct slot *slot; 257 struct slot *slot;
294 258
295 list_for_each_safe(tmp, next, &ctrl->slot_list) { 259 list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
296 slot = list_entry(tmp, struct slot, slot_list);
297 list_del(&slot->slot_list);
298 if (EMI(ctrl)) 260 if (EMI(ctrl))
299 sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj, 261 sysfs_remove_file(&slot->hotplug_slot->pci_slot->kobj,
300 &hotplug_slot_attr_lock.attr); 262 &hotplug_slot_attr_lock.attr);
301 cancel_delayed_work(&slot->work);
302 flush_scheduled_work();
303 flush_workqueue(pciehp_wq);
304 pci_hp_deregister(slot->hotplug_slot); 263 pci_hp_deregister(slot->hotplug_slot);
305 } 264 }
306} 265}
@@ -441,25 +400,13 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_
441 else if (pciehp_get_hp_hw_control_from_firmware(pdev)) 400 else if (pciehp_get_hp_hw_control_from_firmware(pdev))
442 goto err_out_none; 401 goto err_out_none;
443 402
444 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); 403 ctrl = pcie_init(dev);
445 if (!ctrl) { 404 if (!ctrl) {
446 err("%s : out of memory\n", __func__);
447 goto err_out_none;
448 }
449 INIT_LIST_HEAD(&ctrl->slot_list);
450
451 rc = pcie_init(ctrl, dev);
452 if (rc) {
453 dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME); 405 dbg("%s: controller initialization failed\n", PCIE_MODULE_NAME);
454 goto err_out_free_ctrl; 406 goto err_out_none;
455 } 407 }
456
457 pci_set_drvdata(pdev, ctrl); 408 pci_set_drvdata(pdev, ctrl);
458 409
459 dbg("%s: ctrl bus=0x%x, device=%x, function=%x, irq=%x\n",
460 __func__, pdev->bus->number, PCI_SLOT(pdev->devfn),
461 PCI_FUNC(pdev->devfn), pdev->irq);
462
463 /* Setup the slot information structures */ 410 /* Setup the slot information structures */
464 rc = init_slots(ctrl); 411 rc = init_slots(ctrl);
465 if (rc) { 412 if (rc) {
@@ -492,8 +439,6 @@ err_out_free_ctrl_slot:
492 cleanup_slots(ctrl); 439 cleanup_slots(ctrl);
493err_out_release_ctlr: 440err_out_release_ctlr:
494 ctrl->hpc_ops->release_ctlr(ctrl); 441 ctrl->hpc_ops->release_ctlr(ctrl);
495err_out_free_ctrl:
496 kfree(ctrl);
497err_out_none: 442err_out_none:
498 return -ENODEV; 443 return -ENODEV;
499} 444}
@@ -505,7 +450,6 @@ static void pciehp_remove (struct pcie_device *dev)
505 450
506 cleanup_slots(ctrl); 451 cleanup_slots(ctrl);
507 ctrl->hpc_ops->release_ctlr(ctrl); 452 ctrl->hpc_ops->release_ctlr(ctrl);
508 kfree(ctrl);
509} 453}
510 454
511#ifdef CONFIG_PM 455#ifdef CONFIG_PM
@@ -525,7 +469,7 @@ static int pciehp_resume (struct pcie_device *dev)
525 u8 status; 469 u8 status;
526 470
527 /* reinitialize the chipset's event detection logic */ 471 /* reinitialize the chipset's event detection logic */
528 pcie_init_hardware_part2(ctrl, dev); 472 pcie_enable_notification(ctrl);
529 473
530 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 474 t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
531 475
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 59c28093d291..1ce52437e1ed 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -609,23 +609,6 @@ static void hpc_set_green_led_blink(struct slot *slot)
609 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); 609 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
610} 610}
611 611
612static void hpc_release_ctlr(struct controller *ctrl)
613{
614 /* Mask Hot-plug Interrupt Enable */
615 if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE))
616 err("%s: Cannot mask hotplug interrupt enable\n", __func__);
617
618 /* Free interrupt handler or interrupt polling timer */
619 pciehp_free_irq(ctrl);
620
621 /*
622 * If this is the last controller to be released, destroy the
623 * pciehp work queue
624 */
625 if (atomic_dec_and_test(&pciehp_num_controllers))
626 destroy_workqueue(pciehp_wq);
627}
628
629static int hpc_power_on_slot(struct slot * slot) 612static int hpc_power_on_slot(struct slot * slot)
630{ 613{
631 struct controller *ctrl = slot->ctrl; 614 struct controller *ctrl = slot->ctrl;
@@ -798,19 +781,7 @@ static irqreturn_t pcie_isr(int irq, void *dev_id)
798 if (!(intr_loc & ~CMD_COMPLETED)) 781 if (!(intr_loc & ~CMD_COMPLETED))
799 return IRQ_HANDLED; 782 return IRQ_HANDLED;
800 783
801 /*
802 * Return without handling events if this handler routine is
803 * called before controller initialization is done. This may
804 * happen if hotplug event or another interrupt that shares
805 * the IRQ with pciehp arrives before slot initialization is
806 * done after interrupt handler is registered.
807 *
808 * FIXME - Need more structural fixes. We need to be ready to
809 * handle the event before installing interrupt handler.
810 */
811 p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); 784 p_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset);
812 if (!p_slot || !p_slot->hpc_ops)
813 return IRQ_HANDLED;
814 785
815 /* Check MRL Sensor Changed */ 786 /* Check MRL Sensor Changed */
816 if (intr_loc & MRL_SENS_CHANGED) 787 if (intr_loc & MRL_SENS_CHANGED)
@@ -987,6 +958,7 @@ static int hpc_get_cur_lnk_width(struct slot *slot,
987 return retval; 958 return retval;
988} 959}
989 960
961static void pcie_release_ctrl(struct controller *ctrl);
990static struct hpc_ops pciehp_hpc_ops = { 962static struct hpc_ops pciehp_hpc_ops = {
991 .power_on_slot = hpc_power_on_slot, 963 .power_on_slot = hpc_power_on_slot,
992 .power_off_slot = hpc_power_off_slot, 964 .power_off_slot = hpc_power_off_slot,
@@ -1008,28 +980,11 @@ static struct hpc_ops pciehp_hpc_ops = {
1008 .green_led_off = hpc_set_green_led_off, 980 .green_led_off = hpc_set_green_led_off,
1009 .green_led_blink = hpc_set_green_led_blink, 981 .green_led_blink = hpc_set_green_led_blink,
1010 982
1011 .release_ctlr = hpc_release_ctlr, 983 .release_ctlr = pcie_release_ctrl,
1012 .check_lnk_status = hpc_check_lnk_status, 984 .check_lnk_status = hpc_check_lnk_status,
1013}; 985};
1014 986
1015static int pcie_init_hardware_part1(struct controller *ctrl, 987int pcie_enable_notification(struct controller *ctrl)
1016 struct pcie_device *dev)
1017{
1018 /* Clear all remaining event bits in Slot Status register */
1019 if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
1020 err("%s: Cannot write to SLOTSTATUS register\n", __func__);
1021 return -1;
1022 }
1023
1024 /* Mask Hot-plug Interrupt Enable */
1025 if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) {
1026 err("%s: Cannot mask hotplug interrupt enable\n", __func__);
1027 return -1;
1028 }
1029 return 0;
1030}
1031
1032int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
1033{ 988{
1034 u16 cmd, mask; 989 u16 cmd, mask;
1035 990
@@ -1050,10 +1005,76 @@ int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
1050 err("%s: Cannot enable software notification\n", __func__); 1005 err("%s: Cannot enable software notification\n", __func__);
1051 return -1; 1006 return -1;
1052 } 1007 }
1008 return 0;
1009}
1010
1011static void pcie_disable_notification(struct controller *ctrl)
1012{
1013 u16 mask;
1014 mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE | MRL_DETECT_ENABLE |
1015 PWR_FAULT_DETECT_ENABLE | HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE;
1016 if (pcie_write_cmd(ctrl, 0, mask))
1017 warn("%s: Cannot disable software notification\n", __func__);
1018}
1019
1020static int pcie_init_notification(struct controller *ctrl)
1021{
1022 if (pciehp_request_irq(ctrl))
1023 return -1;
1024 if (pcie_enable_notification(ctrl)) {
1025 pciehp_free_irq(ctrl);
1026 return -1;
1027 }
1028 return 0;
1029}
1030
1031static void pcie_shutdown_notification(struct controller *ctrl)
1032{
1033 pcie_disable_notification(ctrl);
1034 pciehp_free_irq(ctrl);
1035}
1036
1037static void make_slot_name(struct slot *slot)
1038{
1039 if (pciehp_slot_with_bus)
1040 snprintf(slot->name, SLOT_NAME_SIZE, "%04d_%04d",
1041 slot->bus, slot->number);
1042 else
1043 snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number);
1044}
1053 1045
1046static int pcie_init_slot(struct controller *ctrl)
1047{
1048 struct slot *slot;
1049
1050 slot = kzalloc(sizeof(*slot), GFP_KERNEL);
1051 if (!slot)
1052 return -ENOMEM;
1053
1054 slot->hp_slot = 0;
1055 slot->ctrl = ctrl;
1056 slot->bus = ctrl->pci_dev->subordinate->number;
1057 slot->device = ctrl->slot_device_offset + slot->hp_slot;
1058 slot->hpc_ops = ctrl->hpc_ops;
1059 slot->number = ctrl->first_slot;
1060 make_slot_name(slot);
1061 mutex_init(&slot->lock);
1062 INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
1063 list_add(&slot->slot_list, &ctrl->slot_list);
1054 return 0; 1064 return 0;
1055} 1065}
1056 1066
1067static void pcie_cleanup_slot(struct controller *ctrl)
1068{
1069 struct slot *slot;
1070 slot = list_first_entry(&ctrl->slot_list, struct slot, slot_list);
1071 list_del(&slot->slot_list);
1072 cancel_delayed_work(&slot->work);
1073 flush_scheduled_work();
1074 flush_workqueue(pciehp_wq);
1075 kfree(slot);
1076}
1077
1057static inline void dbg_ctrl(struct controller *ctrl) 1078static inline void dbg_ctrl(struct controller *ctrl)
1058{ 1079{
1059 int i; 1080 int i;
@@ -1093,11 +1114,19 @@ static inline void dbg_ctrl(struct controller *ctrl)
1093 dbg("Slot Control : 0x%04x\n", reg16); 1114 dbg("Slot Control : 0x%04x\n", reg16);
1094} 1115}
1095 1116
1096int pcie_init(struct controller *ctrl, struct pcie_device *dev) 1117struct controller *pcie_init(struct pcie_device *dev)
1097{ 1118{
1119 struct controller *ctrl;
1098 u32 slot_cap; 1120 u32 slot_cap;
1099 struct pci_dev *pdev = dev->port; 1121 struct pci_dev *pdev = dev->port;
1100 1122
1123 ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
1124 if (!ctrl) {
1125 err("%s : out of memory\n", __func__);
1126 goto abort;
1127 }
1128 INIT_LIST_HEAD(&ctrl->slot_list);
1129
1101 ctrl->pci_dev = pdev; 1130 ctrl->pci_dev = pdev;
1102 ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP); 1131 ctrl->cap_base = pci_find_capability(pdev, PCI_CAP_ID_EXP);
1103 if (!ctrl->cap_base) { 1132 if (!ctrl->cap_base) {
@@ -1128,15 +1157,12 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
1128 !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl))) 1157 !(POWER_CTRL(ctrl) | ATTN_LED(ctrl) | PWR_LED(ctrl) | EMI(ctrl)))
1129 ctrl->no_cmd_complete = 1; 1158 ctrl->no_cmd_complete = 1;
1130 1159
1131 info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n", 1160 /* Clear all remaining event bits in Slot Status register */
1132 pdev->vendor, pdev->device, 1161 if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f))
1133 pdev->subsystem_vendor, pdev->subsystem_device); 1162 goto abort_ctrl;
1134 1163
1135 if (pcie_init_hardware_part1(ctrl, dev)) 1164 /* Disable sotfware notification */
1136 goto abort; 1165 pcie_disable_notification(ctrl);
1137
1138 if (pciehp_request_irq(ctrl))
1139 goto abort;
1140 1166
1141 /* 1167 /*
1142 * If this is the first controller to be initialized, 1168 * If this is the first controller to be initialized,
@@ -1144,18 +1170,39 @@ int pcie_init(struct controller *ctrl, struct pcie_device *dev)
1144 */ 1170 */
1145 if (atomic_add_return(1, &pciehp_num_controllers) == 1) { 1171 if (atomic_add_return(1, &pciehp_num_controllers) == 1) {
1146 pciehp_wq = create_singlethread_workqueue("pciehpd"); 1172 pciehp_wq = create_singlethread_workqueue("pciehpd");
1147 if (!pciehp_wq) { 1173 if (!pciehp_wq)
1148 goto abort_free_irq; 1174 goto abort_ctrl;
1149 }
1150 } 1175 }
1151 1176
1152 if (pcie_init_hardware_part2(ctrl, dev)) 1177 info("HPC vendor_id %x device_id %x ss_vid %x ss_did %x\n",
1153 goto abort_free_irq; 1178 pdev->vendor, pdev->device,
1179 pdev->subsystem_vendor, pdev->subsystem_device);
1180
1181 if (pcie_init_slot(ctrl))
1182 goto abort_ctrl;
1154 1183
1155 return 0; 1184 if (pcie_init_notification(ctrl))
1185 goto abort_slot;
1156 1186
1157abort_free_irq: 1187 return ctrl;
1158 pciehp_free_irq(ctrl); 1188
1189abort_slot:
1190 pcie_cleanup_slot(ctrl);
1191abort_ctrl:
1192 kfree(ctrl);
1159abort: 1193abort:
1160 return -1; 1194 return NULL;
1195}
1196
1197void pcie_release_ctrl(struct controller *ctrl)
1198{
1199 pcie_shutdown_notification(ctrl);
1200 pcie_cleanup_slot(ctrl);
1201 /*
1202 * If this is the last controller to be released, destroy the
1203 * pciehp work queue
1204 */
1205 if (atomic_dec_and_test(&pciehp_num_controllers))
1206 destroy_workqueue(pciehp_wq);
1207 kfree(ctrl);
1161} 1208}