1 /* labelcl - SGI's Hwgraph Compatibility Layer.
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
7 * Copyright (c) 2001-2002 Silicon Graphics, Inc. All rights reserved.
10 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <asm/sn/sgi.h>
13 #include <linux/devfs_fs.h>
14 #include <linux/devfs_fs_kernel.h>
15 #include <asm/sn/invent.h>
16 #include <asm/sn/hcl.h>
17 #include <asm/sn/labelcl.h>
20 ** Very simple and dumb string table that supports only find/insert.
21 ** In practice, if this table gets too large, we may need a more
22 ** efficient data structure. Also note that currently there is no
23 ** way to delete an item once it's added. Therefore, name collision
24 ** will return an error.
27 struct string_table label_string_table;
32 * string_table_init - Initialize the given string table.
35 string_table_init(struct string_table *string_table)
37 string_table->string_table_head = NULL;
38 string_table->string_table_generation = 0;
41 * We nedd to initialize locks here!
49 * string_table_destroy - Destroy the given string table.
52 string_table_destroy(struct string_table *string_table)
54 struct string_table_item *item, *next_item;
56 item = string_table->string_table_head;
58 next_item = item->next;
65 * We need to destroy whatever lock we have here
74 * string_table_insert - Insert an entry in the string table .. duplicate
75 * names are not allowed.
78 string_table_insert(struct string_table *string_table, char *name)
80 struct string_table_item *item, *new_item = NULL, *last_item = NULL;
84 * Need to lock the table ..
86 item = string_table->string_table_head;
90 if (!strcmp(item->string, name)) {
92 * If we allocated space for the string and the found that
93 * someone else already entered it into the string table,
94 * free the space we just allocated.
97 STRTBL_FREE(new_item);
101 * Search optimization: move the found item to the head
104 if (last_item != NULL) {
105 last_item->next = item->next;
106 item->next = string_table->string_table_head;
107 string_table->string_table_head = item;
116 * name was not found, so add it to the string table.
118 if (new_item == NULL) {
119 long old_generation = string_table->string_table_generation;
121 new_item = STRTBL_ALLOC(strlen(name));
123 strcpy(new_item->string, name);
126 * While we allocated memory for the new string, someone else
127 * changed the string table.
129 if (old_generation != string_table->string_table_generation) {
133 /* At this we only have the string table lock in access mode.
134 * Promote the access lock to an update lock for the string
135 * table insertion below.
137 long old_generation =
138 string_table->string_table_generation;
141 * After we did the unlock and wer waiting for update
142 * lock someone could have potentially updated
143 * the string table. Check the generation number
144 * for this case. If it is the case we have to
145 * try all over again.
147 if (old_generation !=
148 string_table->string_table_generation) {
154 * At this point, we're committed to adding new_item to the string table.
156 new_item->next = string_table->string_table_head;
157 item = string_table->string_table_head = new_item;
158 string_table->string_table_generation++;
162 * Need to unlock here.
164 return(item->string);
168 * labelcl_info_create - Creates the data structure that will hold the
169 * device private information asscoiated with a devfs entry.
170 * The pointer to this structure is what gets stored in the devfs
174 labelcl_info_create()
177 labelcl_info_t *new = NULL;
179 /* Initial allocation does not include any area for labels */
180 if ( ( new = (labelcl_info_t *)kmalloc (sizeof(labelcl_info_t), GFP_KERNEL) ) == NULL )
183 memset (new, 0, sizeof(labelcl_info_t));
184 new->hwcl_magic = LABELCL_MAGIC;
190 * labelcl_info_destroy - Frees the data structure that holds the
191 * device private information asscoiated with a devfs entry. This
192 * data structure was created by device_info_create().
194 * The caller is responsible for nulling the (void *info) in the
195 * corresponding devfs entry.
198 labelcl_info_destroy(labelcl_info_t *labelcl_info)
201 if (labelcl_info == NULL)
204 /* Free the label list */
205 if (labelcl_info->label_list)
206 kfree(labelcl_info->label_list);
208 /* Now free the label info area */
209 labelcl_info->hwcl_magic = 0;
216 * labelcl_info_add_LBL - Adds a new label entry in the labelcl info
219 * Error is returned if we find another label with the same name.
222 labelcl_info_add_LBL(devfs_handle_t de,
224 arb_info_desc_t info_desc,
225 arbitrary_info_t info)
227 labelcl_info_t *labelcl_info = NULL;
229 int new_label_list_size;
230 label_info_t *old_label_list, *new_label_list = NULL;
237 labelcl_info = devfs_get_info(de);
238 if (labelcl_info == NULL)
241 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
244 if (info_name == NULL)
247 if (strlen(info_name) >= LABEL_LENGTH_MAX)
250 name = string_table_insert(&label_string_table, info_name);
252 num_labels = labelcl_info->num_labels;
253 new_label_list_size = sizeof(label_info_t) * (num_labels+1);
256 * Create a new label info area.
258 if (new_label_list_size != 0) {
259 new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL);
261 if (new_label_list == NULL)
266 * At this point, we are committed to adding the labelled info,
267 * if there isn't already information there with the same name.
269 old_label_list = labelcl_info->label_list;
272 * Look for matching info name.
274 for (i=0; i<num_labels; i++) {
275 if (!strcmp(info_name, old_label_list[i].name)) {
276 /* Not allowed to add duplicate labelled info names. */
277 kfree(new_label_list);
278 printk(KERN_WARNING "labelcl_info_add_LBL: Duplicate label name %s for vertex 0x%p\n", info_name, (void *)de);
281 new_label_list[i] = old_label_list[i]; /* structure copy */
284 new_label_list[num_labels].name = name;
285 new_label_list[num_labels].desc = info_desc;
286 new_label_list[num_labels].info = info;
288 labelcl_info->num_labels = num_labels+1;
289 labelcl_info->label_list = new_label_list;
291 if (old_label_list != NULL)
292 kfree(old_label_list);
298 * labelcl_info_remove_LBL - Remove a label entry.
301 labelcl_info_remove_LBL(devfs_handle_t de,
303 arb_info_desc_t *info_desc,
304 arbitrary_info_t *info)
306 labelcl_info_t *labelcl_info = NULL;
308 int new_label_list_size;
309 label_info_t *old_label_list, *new_label_list = NULL;
310 arb_info_desc_t label_desc_found;
311 arbitrary_info_t label_info_found;
317 labelcl_info = devfs_get_info(de);
318 if (labelcl_info == NULL)
321 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
324 num_labels = labelcl_info->num_labels;
325 if (num_labels == 0) {
330 * Create a new info area.
332 new_label_list_size = sizeof(label_info_t) * (num_labels-1);
333 if (new_label_list_size) {
334 new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL);
335 if (new_label_list == NULL)
340 * At this point, we are committed to removing the labelled info,
341 * if it still exists.
343 old_label_list = labelcl_info->label_list;
346 * Find matching info name.
348 for (i=0; i<num_labels; i++) {
349 if (!strcmp(info_name, old_label_list[i].name)) {
350 label_desc_found = old_label_list[i].desc;
351 label_info_found = old_label_list[i].info;
354 if (i < num_labels-1) /* avoid walking off the end of the new vertex */
355 new_label_list[i] = old_label_list[i]; /* structure copy */
358 /* The named info doesn't exist. */
360 kfree(new_label_list);
365 /* Finish up rest of labelled info */
366 for (i=i+1; i<num_labels; i++)
367 new_label_list[i-1] = old_label_list[i]; /* structure copy */
369 labelcl_info->num_labels = num_labels+1;
370 labelcl_info->label_list = new_label_list;
372 kfree(old_label_list);
375 *info = label_info_found;
377 if (info_desc != NULL)
378 *info_desc = label_desc_found;
385 * labelcl_info_replace_LBL - Replace an existing label entry with the
386 * given new information.
388 * Label entry must exist.
391 labelcl_info_replace_LBL(devfs_handle_t de,
393 arb_info_desc_t info_desc,
394 arbitrary_info_t info,
395 arb_info_desc_t *old_info_desc,
396 arbitrary_info_t *old_info)
398 labelcl_info_t *labelcl_info = NULL;
400 label_info_t *label_list;
406 labelcl_info = devfs_get_info(de);
407 if (labelcl_info == NULL)
410 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
413 num_labels = labelcl_info->num_labels;
414 if (num_labels == 0) {
418 if (info_name == NULL)
421 label_list = labelcl_info->label_list;
424 * Verify that information under info_name already exists.
426 for (i=0; i<num_labels; i++)
427 if (!strcmp(info_name, label_list[i].name)) {
428 if (old_info != NULL)
429 *old_info = label_list[i].info;
431 if (old_info_desc != NULL)
432 *old_info_desc = label_list[i].desc;
434 label_list[i].info = info;
435 label_list[i].desc = info_desc;
445 * labelcl_info_get_LBL - Retrieve and return the information for the
449 labelcl_info_get_LBL(devfs_handle_t de,
451 arb_info_desc_t *info_desc,
452 arbitrary_info_t *info)
454 labelcl_info_t *labelcl_info = NULL;
456 label_info_t *label_list;
462 labelcl_info = devfs_get_info(de);
463 if (labelcl_info == NULL)
466 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
469 num_labels = labelcl_info->num_labels;
470 if (num_labels == 0) {
474 label_list = labelcl_info->label_list;
477 * Find information under info_name.
479 for (i=0; i<num_labels; i++)
480 if (!strcmp(info_name, label_list[i].name)) {
482 *info = label_list[i].info;
483 if (info_desc != NULL)
484 *info_desc = label_list[i].desc;
493 * labelcl_info_get_next_LBL - returns the next label entry on the list.
496 labelcl_info_get_next_LBL(devfs_handle_t de,
498 arb_info_desc_t *info_descp,
499 arbitrary_info_t *infop,
500 labelcl_info_place_t *placeptr)
502 labelcl_info_t *labelcl_info = NULL;
504 label_info_t *label_list;
506 if ((buffer == NULL) && (infop == NULL))
509 if (placeptr == NULL)
515 labelcl_info = devfs_get_info(de);
516 if (labelcl_info == NULL)
519 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
522 which_info = *placeptr;
524 if (which_info >= labelcl_info->num_labels) {
528 label_list = (label_info_t *) labelcl_info->label_list;
531 strcpy(buffer, label_list[which_info].name);
534 *infop = label_list[which_info].info;
537 *info_descp = label_list[which_info].desc;
539 *placeptr = which_info + 1;
546 labelcl_info_replace_IDX(devfs_handle_t de,
548 arbitrary_info_t info,
549 arbitrary_info_t *old_info)
551 arbitrary_info_t *info_list_IDX;
552 labelcl_info_t *labelcl_info = NULL;
555 printk(KERN_ALERT "labelcl: NULL devfs handle given.\n");
559 labelcl_info = devfs_get_info(de);
560 if (labelcl_info == NULL) {
561 printk(KERN_ALERT "labelcl: Entry does not have info pointer.\n");
565 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
568 if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) )
572 * Replace information at the appropriate index in this vertex with
575 info_list_IDX = labelcl_info->IDX_list;
576 if (old_info != NULL)
577 *old_info = info_list_IDX[index];
578 info_list_IDX[index] = info;
585 * labelcl_info_connectpt_set - Sets the connectpt.
588 labelcl_info_connectpt_set(struct devfs_entry *de,
589 struct devfs_entry *connect_de)
591 arbitrary_info_t old_info;
594 rv = labelcl_info_replace_IDX(de, HWGRAPH_CONNECTPT,
595 (arbitrary_info_t) connect_de, &old_info);
606 * labelcl_info_get_IDX - Returns the information pointed at by index.
610 labelcl_info_get_IDX(devfs_handle_t de,
612 arbitrary_info_t *info)
614 arbitrary_info_t *info_list_IDX;
615 labelcl_info_t *labelcl_info = NULL;
620 labelcl_info = devfs_get_info(de);
621 if (labelcl_info == NULL)
624 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
627 if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) )
631 * Return information at the appropriate index in this vertex.
633 info_list_IDX = labelcl_info->IDX_list;
635 *info = info_list_IDX[index];
641 * labelcl_info_connectpt_get - Retrieve the connect point for a device entry.
644 labelcl_info_connectpt_get(struct devfs_entry *de)
647 arbitrary_info_t info;
649 rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info);
653 return((struct devfs_entry *)info);