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-2003 Silicon Graphics, Inc. All rights reserved.
10 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <linux/kernel.h>
14 #include <linux/string.h>
15 #include <linux/sched.h> /* needed for smp_lock.h :( */
16 #include <linux/smp_lock.h>
17 #include <asm/sn/sgi.h>
18 #include <asm/sn/hwgfs.h>
19 #include <asm/sn/invent.h>
20 #include <asm/sn/hcl.h>
21 #include <asm/sn/labelcl.h>
24 ** Very simple and dumb string table that supports only find/insert.
25 ** In practice, if this table gets too large, we may need a more
26 ** efficient data structure. Also note that currently there is no
27 ** way to delete an item once it's added. Therefore, name collision
28 ** will return an error.
31 struct string_table label_string_table;
36 * string_table_init - Initialize the given string table.
39 string_table_init(struct string_table *string_table)
41 string_table->string_table_head = NULL;
42 string_table->string_table_generation = 0;
45 * We nedd to initialize locks here!
53 * string_table_destroy - Destroy the given string table.
56 string_table_destroy(struct string_table *string_table)
58 struct string_table_item *item, *next_item;
60 item = string_table->string_table_head;
62 next_item = item->next;
69 * We need to destroy whatever lock we have here
78 * string_table_insert - Insert an entry in the string table .. duplicate
79 * names are not allowed.
82 string_table_insert(struct string_table *string_table, char *name)
84 struct string_table_item *item, *new_item = NULL, *last_item = NULL;
88 * Need to lock the table ..
90 item = string_table->string_table_head;
94 if (!strcmp(item->string, name)) {
96 * If we allocated space for the string and the found that
97 * someone else already entered it into the string table,
98 * free the space we just allocated.
101 STRTBL_FREE(new_item);
105 * Search optimization: move the found item to the head
108 if (last_item != NULL) {
109 last_item->next = item->next;
110 item->next = string_table->string_table_head;
111 string_table->string_table_head = item;
120 * name was not found, so add it to the string table.
122 if (new_item == NULL) {
123 long old_generation = string_table->string_table_generation;
125 new_item = STRTBL_ALLOC(strlen(name));
127 strcpy(new_item->string, name);
130 * While we allocated memory for the new string, someone else
131 * changed the string table.
133 if (old_generation != string_table->string_table_generation) {
137 /* At this we only have the string table lock in access mode.
138 * Promote the access lock to an update lock for the string
139 * table insertion below.
141 long old_generation =
142 string_table->string_table_generation;
145 * After we did the unlock and wer waiting for update
146 * lock someone could have potentially updated
147 * the string table. Check the generation number
148 * for this case. If it is the case we have to
149 * try all over again.
151 if (old_generation !=
152 string_table->string_table_generation) {
158 * At this point, we're committed to adding new_item to the string table.
160 new_item->next = string_table->string_table_head;
161 item = string_table->string_table_head = new_item;
162 string_table->string_table_generation++;
166 * Need to unlock here.
168 return(item->string);
172 * labelcl_info_create - Creates the data structure that will hold the
173 * device private information asscoiated with a entry.
174 * The pointer to this structure is what gets stored in the
178 labelcl_info_create()
181 labelcl_info_t *new = NULL;
183 /* Initial allocation does not include any area for labels */
184 if ( ( new = (labelcl_info_t *)kmalloc (sizeof(labelcl_info_t), GFP_KERNEL) ) == NULL )
187 memset (new, 0, sizeof(labelcl_info_t));
188 new->hwcl_magic = LABELCL_MAGIC;
194 * labelcl_info_destroy - Frees the data structure that holds the
195 * device private information asscoiated with a entry. This
196 * data structure was created by device_info_create().
198 * The caller is responsible for nulling the (void *info) in the
199 * corresponding entry.
202 labelcl_info_destroy(labelcl_info_t *labelcl_info)
205 if (labelcl_info == NULL)
208 /* Free the label list */
209 if (labelcl_info->label_list)
210 kfree(labelcl_info->label_list);
212 /* Now free the label info area */
213 labelcl_info->hwcl_magic = 0;
220 * labelcl_info_add_LBL - Adds a new label entry in the labelcl info
223 * Error is returned if we find another label with the same name.
226 labelcl_info_add_LBL(vertex_hdl_t de,
228 arb_info_desc_t info_desc,
229 arbitrary_info_t info)
231 labelcl_info_t *labelcl_info = NULL;
233 int new_label_list_size;
234 label_info_t *old_label_list, *new_label_list = NULL;
241 labelcl_info = hwgfs_get_info(de);
242 if (labelcl_info == NULL)
245 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
248 if (info_name == NULL)
251 if (strlen(info_name) >= LABEL_LENGTH_MAX)
254 name = string_table_insert(&label_string_table, info_name);
256 num_labels = labelcl_info->num_labels;
257 new_label_list_size = sizeof(label_info_t) * (num_labels+1);
260 * Create a new label info area.
262 if (new_label_list_size != 0) {
263 new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL);
265 if (new_label_list == NULL)
270 * At this point, we are committed to adding the labelled info,
271 * if there isn't already information there with the same name.
273 old_label_list = labelcl_info->label_list;
276 * Look for matching info name.
278 for (i=0; i<num_labels; i++) {
279 if (!strcmp(info_name, old_label_list[i].name)) {
280 /* Not allowed to add duplicate labelled info names. */
281 kfree(new_label_list);
284 new_label_list[i] = old_label_list[i]; /* structure copy */
287 new_label_list[num_labels].name = name;
288 new_label_list[num_labels].desc = info_desc;
289 new_label_list[num_labels].info = info;
291 labelcl_info->num_labels = num_labels+1;
292 labelcl_info->label_list = new_label_list;
294 if (old_label_list != NULL)
295 kfree(old_label_list);
301 * labelcl_info_remove_LBL - Remove a label entry.
304 labelcl_info_remove_LBL(vertex_hdl_t de,
306 arb_info_desc_t *info_desc,
307 arbitrary_info_t *info)
309 labelcl_info_t *labelcl_info = NULL;
311 int new_label_list_size;
312 label_info_t *old_label_list, *new_label_list = NULL;
313 arb_info_desc_t label_desc_found;
314 arbitrary_info_t label_info_found;
320 labelcl_info = hwgfs_get_info(de);
321 if (labelcl_info == NULL)
324 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
327 num_labels = labelcl_info->num_labels;
328 if (num_labels == 0) {
333 * Create a new info area.
335 new_label_list_size = sizeof(label_info_t) * (num_labels-1);
336 if (new_label_list_size) {
337 new_label_list = (label_info_t *) kmalloc(new_label_list_size, GFP_KERNEL);
338 if (new_label_list == NULL)
343 * At this point, we are committed to removing the labelled info,
344 * if it still exists.
346 old_label_list = labelcl_info->label_list;
349 * Find matching info name.
351 for (i=0; i<num_labels; i++) {
352 if (!strcmp(info_name, old_label_list[i].name)) {
353 label_desc_found = old_label_list[i].desc;
354 label_info_found = old_label_list[i].info;
357 if (i < num_labels-1) /* avoid walking off the end of the new vertex */
358 new_label_list[i] = old_label_list[i]; /* structure copy */
361 /* The named info doesn't exist. */
363 kfree(new_label_list);
368 /* Finish up rest of labelled info */
369 for (i=i+1; i<num_labels; i++)
370 new_label_list[i-1] = old_label_list[i]; /* structure copy */
372 labelcl_info->num_labels = num_labels+1;
373 labelcl_info->label_list = new_label_list;
375 kfree(old_label_list);
378 *info = label_info_found;
380 if (info_desc != NULL)
381 *info_desc = label_desc_found;
388 * labelcl_info_replace_LBL - Replace an existing label entry with the
389 * given new information.
391 * Label entry must exist.
394 labelcl_info_replace_LBL(vertex_hdl_t de,
396 arb_info_desc_t info_desc,
397 arbitrary_info_t info,
398 arb_info_desc_t *old_info_desc,
399 arbitrary_info_t *old_info)
401 labelcl_info_t *labelcl_info = NULL;
403 label_info_t *label_list;
409 labelcl_info = hwgfs_get_info(de);
410 if (labelcl_info == NULL)
413 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
416 num_labels = labelcl_info->num_labels;
417 if (num_labels == 0) {
421 if (info_name == NULL)
424 label_list = labelcl_info->label_list;
427 * Verify that information under info_name already exists.
429 for (i=0; i<num_labels; i++)
430 if (!strcmp(info_name, label_list[i].name)) {
431 if (old_info != NULL)
432 *old_info = label_list[i].info;
434 if (old_info_desc != NULL)
435 *old_info_desc = label_list[i].desc;
437 label_list[i].info = info;
438 label_list[i].desc = info_desc;
448 * labelcl_info_get_LBL - Retrieve and return the information for the
452 labelcl_info_get_LBL(vertex_hdl_t de,
454 arb_info_desc_t *info_desc,
455 arbitrary_info_t *info)
457 labelcl_info_t *labelcl_info = NULL;
459 label_info_t *label_list;
465 labelcl_info = hwgfs_get_info(de);
466 if (labelcl_info == NULL)
469 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
472 num_labels = labelcl_info->num_labels;
473 if (num_labels == 0) {
477 label_list = labelcl_info->label_list;
480 * Find information under info_name.
482 for (i=0; i<num_labels; i++)
483 if (!strcmp(info_name, label_list[i].name)) {
485 *info = label_list[i].info;
486 if (info_desc != NULL)
487 *info_desc = label_list[i].desc;
496 * labelcl_info_get_next_LBL - returns the next label entry on the list.
499 labelcl_info_get_next_LBL(vertex_hdl_t de,
501 arb_info_desc_t *info_descp,
502 arbitrary_info_t *infop,
503 labelcl_info_place_t *placeptr)
505 labelcl_info_t *labelcl_info = NULL;
507 label_info_t *label_list;
509 if ((buffer == NULL) && (infop == NULL))
512 if (placeptr == NULL)
518 labelcl_info = hwgfs_get_info(de);
519 if (labelcl_info == NULL)
522 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
525 which_info = *placeptr;
527 if (which_info >= labelcl_info->num_labels) {
531 label_list = (label_info_t *) labelcl_info->label_list;
534 strcpy(buffer, label_list[which_info].name);
537 *infop = label_list[which_info].info;
540 *info_descp = label_list[which_info].desc;
542 *placeptr = which_info + 1;
549 labelcl_info_replace_IDX(vertex_hdl_t de,
551 arbitrary_info_t info,
552 arbitrary_info_t *old_info)
554 arbitrary_info_t *info_list_IDX;
555 labelcl_info_t *labelcl_info = NULL;
558 printk(KERN_ALERT "labelcl: NULL handle given.\n");
562 labelcl_info = hwgfs_get_info(de);
563 if (labelcl_info == NULL) {
564 printk(KERN_ALERT "labelcl: Entry %p does not have info pointer.\n", (void *)de);
568 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
571 if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) )
575 * Replace information at the appropriate index in this vertex with
578 info_list_IDX = labelcl_info->IDX_list;
579 if (old_info != NULL)
580 *old_info = info_list_IDX[index];
581 info_list_IDX[index] = info;
588 * labelcl_info_connectpt_set - Sets the connectpt.
591 labelcl_info_connectpt_set(hwgfs_handle_t de,
592 hwgfs_handle_t connect_de)
594 arbitrary_info_t old_info;
597 rv = labelcl_info_replace_IDX(de, HWGRAPH_CONNECTPT,
598 (arbitrary_info_t) connect_de, &old_info);
609 * labelcl_info_get_IDX - Returns the information pointed at by index.
613 labelcl_info_get_IDX(vertex_hdl_t de,
615 arbitrary_info_t *info)
617 arbitrary_info_t *info_list_IDX;
618 labelcl_info_t *labelcl_info = NULL;
623 labelcl_info = hwgfs_get_info(de);
624 if (labelcl_info == NULL)
627 if (labelcl_info->hwcl_magic != LABELCL_MAGIC)
630 if ( (index < 0) || (index >= HWGRAPH_NUM_INDEX_INFO) )
634 * Return information at the appropriate index in this vertex.
636 info_list_IDX = labelcl_info->IDX_list;
638 *info = info_list_IDX[index];
644 * labelcl_info_connectpt_get - Retrieve the connect point for a device entry.
647 labelcl_info_connectpt_get(hwgfs_handle_t de)
650 arbitrary_info_t info;
652 rv = labelcl_info_get_IDX(de, HWGRAPH_CONNECTPT, &info);
656 return((hwgfs_handle_t) info);