X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fieee1394%2Fieee1394_core.c;h=ee45259573c8b3c9450637e07047bb5f58ab9d2b;hb=831441862956fffa17b9801db37e6ea1650b0f69;hp=857e46c6e386bee18526b04b29f8936ade76ffee;hpb=afd6546d8d2d8ba1dbe1d2508baf81eebdca3d79;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/ieee1394/ieee1394_core.c b/drivers/ieee1394/ieee1394_core.c index 857e46c..ee45259 100644 --- a/drivers/ieee1394/ieee1394_core.c +++ b/drivers/ieee1394/ieee1394_core.c @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include #include @@ -103,6 +103,8 @@ static void queue_packet_complete(struct hpsb_packet *packet); * * Set the task that runs when a packet completes. You cannot call this more * than once on a single packet before it is sent. + * + * Typically, the complete @routine is responsible to call hpsb_free_packet(). */ void hpsb_set_packet_complete_task(struct hpsb_packet *packet, void (*routine)(void *), void *data) @@ -115,12 +117,12 @@ void hpsb_set_packet_complete_task(struct hpsb_packet *packet, /** * hpsb_alloc_packet - allocate new packet structure - * @data_size: size of the data block to be allocated + * @data_size: size of the data block to be allocated, in bytes * * This function allocates, initializes and returns a new &struct hpsb_packet. - * It can be used in interrupt context. A header block is always included, its - * size is big enough to contain all possible 1394 headers. The data block is - * only allocated when @data_size is not zero. + * It can be used in interrupt context. A header block is always included and + * initialized with zeros. Its size is big enough to contain all possible 1394 + * headers. The data block is only allocated if @data_size is not zero. * * For packets for which responses will be received the @data_size has to be big * enough to contain the response's data block since no further allocation @@ -135,50 +137,42 @@ void hpsb_set_packet_complete_task(struct hpsb_packet *packet, */ struct hpsb_packet *hpsb_alloc_packet(size_t data_size) { - struct hpsb_packet *packet = NULL; - struct sk_buff *skb; + struct hpsb_packet *packet; data_size = ((data_size + 3) & ~3); - skb = alloc_skb(data_size + sizeof(*packet), GFP_ATOMIC); - if (skb == NULL) + packet = kzalloc(sizeof(*packet) + data_size, GFP_ATOMIC); + if (!packet) return NULL; - memset(skb->data, 0, data_size + sizeof(*packet)); - - packet = (struct hpsb_packet *)skb->data; - packet->skb = skb; - - packet->header = packet->embedded_header; packet->state = hpsb_unused; packet->generation = -1; INIT_LIST_HEAD(&packet->driver_list); + INIT_LIST_HEAD(&packet->queue); atomic_set(&packet->refcnt, 1); if (data_size) { - packet->data = (quadlet_t *)(skb->data + sizeof(*packet)); - packet->data_size = data_size; + packet->data = packet->embedded_data; + packet->allocated_data_size = data_size; } - return packet; } - /** * hpsb_free_packet - free packet and data associated with it * @packet: packet to free (is NULL safe) * - * This function will free packet->data and finally the packet itself. + * Frees @packet->data only if it was allocated through hpsb_alloc_packet(). */ void hpsb_free_packet(struct hpsb_packet *packet) { if (packet && atomic_dec_and_test(&packet->refcnt)) { - BUG_ON(!list_empty(&packet->driver_list)); - kfree_skb(packet->skb); + BUG_ON(!list_empty(&packet->driver_list) || + !list_empty(&packet->queue)); + kfree(packet); } } - /** * hpsb_reset_bus - initiate bus reset on the given host * @host: host controller whose bus to reset @@ -494,6 +488,8 @@ void hpsb_selfid_complete(struct hpsb_host *host, int phyid, int isroot) highlevel_host_reset(host); } +static spinlock_t pending_packets_lock = SPIN_LOCK_UNLOCKED; + /** * hpsb_packet_sent - notify core of sending a packet * @@ -509,24 +505,24 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, { unsigned long flags; - spin_lock_irqsave(&host->pending_packet_queue.lock, flags); + spin_lock_irqsave(&pending_packets_lock, flags); packet->ack_code = ackcode; if (packet->no_waiter || packet->state == hpsb_complete) { /* if packet->no_waiter, must not have a tlabel allocated */ - spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags); + spin_unlock_irqrestore(&pending_packets_lock, flags); hpsb_free_packet(packet); return; } atomic_dec(&packet->refcnt); /* drop HC's reference */ - /* here the packet must be on the host->pending_packet_queue */ + /* here the packet must be on the host->pending_packets queue */ if (ackcode != ACK_PENDING || !packet->expect_response) { packet->state = hpsb_complete; - __skb_unlink(packet->skb, &host->pending_packet_queue); - spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags); + list_del_init(&packet->queue); + spin_unlock_irqrestore(&pending_packets_lock, flags); queue_packet_complete(packet); return; } @@ -534,7 +530,7 @@ void hpsb_packet_sent(struct hpsb_host *host, struct hpsb_packet *packet, packet->state = hpsb_pending; packet->sendtime = jiffies; - spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags); + spin_unlock_irqrestore(&pending_packets_lock, flags); mod_timer(&host->timeout, jiffies + host->timeout_interval); } @@ -609,12 +605,16 @@ int hpsb_send_packet(struct hpsb_packet *packet) WARN_ON(packet->no_waiter && packet->expect_response); if (!packet->no_waiter || packet->expect_response) { + unsigned long flags; + atomic_inc(&packet->refcnt); /* Set the initial "sendtime" to 10 seconds from now, to prevent premature expiry. If a packet takes more than 10 seconds to hit the wire, we have bigger problems :) */ packet->sendtime = jiffies + 10 * HZ; - skb_queue_tail(&host->pending_packet_queue, packet->skb); + spin_lock_irqsave(&pending_packets_lock, flags); + list_add_tail(&packet->queue, &host->pending_packets); + spin_unlock_irqrestore(&pending_packets_lock, flags); } if (packet->node_id == host->node_id) { @@ -690,86 +690,97 @@ static void send_packet_nocare(struct hpsb_packet *packet) } } +static size_t packet_size_to_data_size(size_t packet_size, size_t header_size, + size_t buffer_size, int tcode) +{ + size_t ret = packet_size <= header_size ? 0 : packet_size - header_size; + + if (unlikely(ret > buffer_size)) + ret = buffer_size; + + if (unlikely(ret + header_size != packet_size)) + HPSB_ERR("unexpected packet size %zd (tcode %d), bug?", + packet_size, tcode); + return ret; +} static void handle_packet_response(struct hpsb_host *host, int tcode, quadlet_t *data, size_t size) { - struct hpsb_packet *packet = NULL; - struct sk_buff *skb; - int tcode_match = 0; - int tlabel; + struct hpsb_packet *packet; + int tlabel = (data[0] >> 10) & 0x3f; + size_t header_size; unsigned long flags; - tlabel = (data[0] >> 10) & 0x3f; - - spin_lock_irqsave(&host->pending_packet_queue.lock, flags); - - skb_queue_walk(&host->pending_packet_queue, skb) { - packet = (struct hpsb_packet *)skb->data; - if ((packet->tlabel == tlabel) - && (packet->node_id == (data[1] >> 16))){ - break; - } + spin_lock_irqsave(&pending_packets_lock, flags); - packet = NULL; - } + list_for_each_entry(packet, &host->pending_packets, queue) + if (packet->tlabel == tlabel && + packet->node_id == (data[1] >> 16)) + goto found; - if (packet == NULL) { - HPSB_DEBUG("unsolicited response packet received - no tlabel match"); - dump_packet("contents", data, 16, -1); - spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags); - return; - } + spin_unlock_irqrestore(&pending_packets_lock, flags); + HPSB_DEBUG("unsolicited response packet received - %s", + "no tlabel match"); + dump_packet("contents", data, 16, -1); + return; +found: switch (packet->tcode) { case TCODE_WRITEQ: case TCODE_WRITEB: - if (tcode != TCODE_WRITE_RESPONSE) + if (unlikely(tcode != TCODE_WRITE_RESPONSE)) break; - tcode_match = 1; - memcpy(packet->header, data, 12); - break; + header_size = 12; + size = 0; + goto dequeue; + case TCODE_READQ: - if (tcode != TCODE_READQ_RESPONSE) + if (unlikely(tcode != TCODE_READQ_RESPONSE)) break; - tcode_match = 1; - memcpy(packet->header, data, 16); - break; + header_size = 16; + size = 0; + goto dequeue; + case TCODE_READB: - if (tcode != TCODE_READB_RESPONSE) + if (unlikely(tcode != TCODE_READB_RESPONSE)) break; - tcode_match = 1; - BUG_ON(packet->skb->len - sizeof(*packet) < size - 16); - memcpy(packet->header, data, 16); - memcpy(packet->data, data + 4, size - 16); - break; + header_size = 16; + size = packet_size_to_data_size(size, header_size, + packet->allocated_data_size, + tcode); + goto dequeue; + case TCODE_LOCK_REQUEST: - if (tcode != TCODE_LOCK_RESPONSE) + if (unlikely(tcode != TCODE_LOCK_RESPONSE)) break; - tcode_match = 1; - size = min((size - 16), (size_t)8); - BUG_ON(packet->skb->len - sizeof(*packet) < size); - memcpy(packet->header, data, 16); - memcpy(packet->data, data + 4, size); - break; + header_size = 16; + size = packet_size_to_data_size(min(size, (size_t)(16 + 8)), + header_size, + packet->allocated_data_size, + tcode); + goto dequeue; } - if (!tcode_match) { - spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags); - HPSB_INFO("unsolicited response packet received - tcode mismatch"); - dump_packet("contents", data, 16, -1); - return; - } + spin_unlock_irqrestore(&pending_packets_lock, flags); + HPSB_DEBUG("unsolicited response packet received - %s", + "tcode mismatch"); + dump_packet("contents", data, 16, -1); + return; - __skb_unlink(skb, &host->pending_packet_queue); +dequeue: + list_del_init(&packet->queue); + spin_unlock_irqrestore(&pending_packets_lock, flags); if (packet->state == hpsb_queued) { packet->sendtime = jiffies; packet->ack_code = ACK_PENDING; } - packet->state = hpsb_complete; - spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags); + + memcpy(packet->header, data, header_size); + if (size) + memcpy(packet->data, data + 4, size); queue_packet_complete(packet); } @@ -783,6 +794,7 @@ static struct hpsb_packet *create_reply_packet(struct hpsb_host *host, p = hpsb_alloc_packet(dsize); if (unlikely(p == NULL)) { /* FIXME - send data_error response */ + HPSB_ERR("out of memory, cannot send response packet"); return NULL; } @@ -832,7 +844,6 @@ static void fill_async_readblock_resp(struct hpsb_packet *packet, int rcode, static void fill_async_write_resp(struct hpsb_packet *packet, int rcode) { PREP_ASYNC_HEAD_RCODE(TCODE_WRITE_RESPONSE); - packet->header[2] = 0; packet->header_size = 12; packet->data_size = 0; } @@ -849,12 +860,9 @@ static void fill_async_lock_resp(struct hpsb_packet *packet, int rcode, int extc packet->data_size = length; } -#define PREP_REPLY_PACKET(length) \ - packet = create_reply_packet(host, data, length); \ - if (packet == NULL) break - static void handle_incoming_packet(struct hpsb_host *host, int tcode, - quadlet_t *data, size_t size, int write_acked) + quadlet_t *data, size_t size, + int write_acked) { struct hpsb_packet *packet; int length, rcode, extcode; @@ -864,74 +872,72 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode, u16 flags = (u16) data[0]; u64 addr; - /* big FIXME - no error checking is done for an out of bounds length */ + /* FIXME? + * Out-of-bounds lengths are left for highlevel_read|write to cap. */ switch (tcode) { case TCODE_WRITEQ: addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_write(host, source, dest, data+3, + rcode = highlevel_write(host, source, dest, data + 3, addr, 4, flags); - - if (!write_acked - && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK) - && (rcode >= 0)) { - /* not a broadcast write, reply */ - PREP_REPLY_PACKET(0); - fill_async_write_resp(packet, rcode); - send_packet_nocare(packet); - } - break; + goto handle_write_request; case TCODE_WRITEB: addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - rcode = highlevel_write(host, source, dest, data+4, - addr, data[3]>>16, flags); - - if (!write_acked - && (NODEID_TO_NODE(data[0] >> 16) != NODE_MASK) - && (rcode >= 0)) { - /* not a broadcast write, reply */ - PREP_REPLY_PACKET(0); + rcode = highlevel_write(host, source, dest, data + 4, + addr, data[3] >> 16, flags); +handle_write_request: + if (rcode < 0 || write_acked || + NODEID_TO_NODE(data[0] >> 16) == NODE_MASK) + return; + /* not a broadcast write, reply */ + packet = create_reply_packet(host, data, 0); + if (packet) { fill_async_write_resp(packet, rcode); send_packet_nocare(packet); } - break; + return; case TCODE_READQ: addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; rcode = highlevel_read(host, source, &buffer, addr, 4, flags); + if (rcode < 0) + return; - if (rcode >= 0) { - PREP_REPLY_PACKET(0); + packet = create_reply_packet(host, data, 0); + if (packet) { fill_async_readquad_resp(packet, rcode, buffer); send_packet_nocare(packet); } - break; + return; case TCODE_READB: length = data[3] >> 16; - PREP_REPLY_PACKET(length); + packet = create_reply_packet(host, data, length); + if (!packet) + return; addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; rcode = highlevel_read(host, source, packet->data, addr, length, flags); - - if (rcode >= 0) { - fill_async_readblock_resp(packet, rcode, length); - send_packet_nocare(packet); - } else { + if (rcode < 0) { hpsb_free_packet(packet); + return; } - break; + fill_async_readblock_resp(packet, rcode, length); + send_packet_nocare(packet); + return; case TCODE_LOCK_REQUEST: length = data[3] >> 16; extcode = data[3] & 0xffff; addr = (((u64)(data[1] & 0xffff)) << 32) | data[2]; - PREP_REPLY_PACKET(8); + packet = create_reply_packet(host, data, 8); + if (!packet) + return; - if ((extcode == 0) || (extcode >= 7)) { + if (extcode == 0 || extcode >= 7) { /* let switch default handle error */ length = 0; } @@ -939,12 +945,12 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode, switch (length) { case 4: rcode = highlevel_lock(host, source, packet->data, addr, - data[4], 0, extcode,flags); + data[4], 0, extcode, flags); fill_async_lock_resp(packet, rcode, extcode, 4); break; case 8: - if ((extcode != EXTCODE_FETCH_ADD) - && (extcode != EXTCODE_LITTLE_ADD)) { + if (extcode != EXTCODE_FETCH_ADD && + extcode != EXTCODE_LITTLE_ADD) { rcode = highlevel_lock(host, source, packet->data, addr, data[5], data[4], @@ -968,20 +974,16 @@ static void handle_incoming_packet(struct hpsb_host *host, int tcode, break; default: rcode = RCODE_TYPE_ERROR; - fill_async_lock_resp(packet, rcode, - extcode, 0); + fill_async_lock_resp(packet, rcode, extcode, 0); } - if (rcode >= 0) { - send_packet_nocare(packet); - } else { + if (rcode < 0) hpsb_free_packet(packet); - } - break; + else + send_packet_nocare(packet); + return; } - } -#undef PREP_REPLY_PACKET /** * hpsb_packet_received - hand over received packet to the core @@ -1002,8 +1004,8 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, { int tcode; - if (host->in_bus_reset) { - HPSB_INFO("received packet during reset; ignoring"); + if (unlikely(host->in_bus_reset)) { + HPSB_DEBUG("received packet during reset; ignoring"); return; } @@ -1027,33 +1029,32 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, handle_incoming_packet(host, tcode, data, size, write_acked); break; - - case TCODE_ISO_DATA: - highlevel_iso_receive(host, data, size); - break; - case TCODE_CYCLE_START: /* simply ignore this packet if it is passed on */ break; default: - HPSB_NOTICE("received packet with bogus transaction code %d", - tcode); + HPSB_DEBUG("received packet with bogus transaction code %d", + tcode); break; } } - static void abort_requests(struct hpsb_host *host) { - struct hpsb_packet *packet; - struct sk_buff *skb; + struct hpsb_packet *packet, *p; + struct list_head tmp; + unsigned long flags; host->driver->devctl(host, CANCEL_REQUESTS, 0); - while ((skb = skb_dequeue(&host->pending_packet_queue)) != NULL) { - packet = (struct hpsb_packet *)skb->data; + INIT_LIST_HEAD(&tmp); + spin_lock_irqsave(&pending_packets_lock, flags); + list_splice_init(&host->pending_packets, &tmp); + spin_unlock_irqrestore(&pending_packets_lock, flags); + list_for_each_entry_safe(packet, p, &tmp, queue) { + list_del_init(&packet->queue); packet->state = hpsb_complete; packet->ack_code = ACKX_ABORTED; queue_packet_complete(packet); @@ -1063,87 +1064,88 @@ static void abort_requests(struct hpsb_host *host) void abort_timedouts(unsigned long __opaque) { struct hpsb_host *host = (struct hpsb_host *)__opaque; - unsigned long flags; - struct hpsb_packet *packet; - struct sk_buff *skb; - unsigned long expire; + struct hpsb_packet *packet, *p; + struct list_head tmp; + unsigned long flags, expire, j; spin_lock_irqsave(&host->csr.lock, flags); expire = host->csr.expire; spin_unlock_irqrestore(&host->csr.lock, flags); - /* Hold the lock around this, since we aren't dequeuing all - * packets, just ones we need. */ - spin_lock_irqsave(&host->pending_packet_queue.lock, flags); - - while (!skb_queue_empty(&host->pending_packet_queue)) { - skb = skb_peek(&host->pending_packet_queue); + j = jiffies; + INIT_LIST_HEAD(&tmp); + spin_lock_irqsave(&pending_packets_lock, flags); - packet = (struct hpsb_packet *)skb->data; - - if (time_before(packet->sendtime + expire, jiffies)) { - __skb_unlink(skb, &host->pending_packet_queue); - packet->state = hpsb_complete; - packet->ack_code = ACKX_TIMEOUT; - queue_packet_complete(packet); - } else { + list_for_each_entry_safe(packet, p, &host->pending_packets, queue) { + if (time_before(packet->sendtime + expire, j)) + list_move_tail(&packet->queue, &tmp); + else /* Since packets are added to the tail, the oldest * ones are first, always. When we get to one that * isn't timed out, the rest aren't either. */ break; - } } + if (!list_empty(&host->pending_packets)) + mod_timer(&host->timeout, j + host->timeout_interval); - if (!skb_queue_empty(&host->pending_packet_queue)) - mod_timer(&host->timeout, jiffies + host->timeout_interval); + spin_unlock_irqrestore(&pending_packets_lock, flags); - spin_unlock_irqrestore(&host->pending_packet_queue.lock, flags); + list_for_each_entry_safe(packet, p, &tmp, queue) { + list_del_init(&packet->queue); + packet->state = hpsb_complete; + packet->ack_code = ACKX_TIMEOUT; + queue_packet_complete(packet); + } } - -/* Kernel thread and vars, which handles packets that are completed. Only - * packets that have a "complete" function are sent here. This way, the - * completion is run out of kernel context, and doesn't block the rest of - * the stack. */ static struct task_struct *khpsbpkt_thread; -static struct sk_buff_head hpsbpkt_queue; +static LIST_HEAD(hpsbpkt_queue); static void queue_packet_complete(struct hpsb_packet *packet) { + unsigned long flags; + if (packet->no_waiter) { hpsb_free_packet(packet); return; } if (packet->complete_routine != NULL) { - skb_queue_tail(&hpsbpkt_queue, packet->skb); + spin_lock_irqsave(&pending_packets_lock, flags); + list_add_tail(&packet->queue, &hpsbpkt_queue); + spin_unlock_irqrestore(&pending_packets_lock, flags); wake_up_process(khpsbpkt_thread); } return; } +/* + * Kernel thread which handles packets that are completed. This way the + * packet's "complete" function is asynchronously run in process context. + * Only packets which have a "complete" function may be sent here. + */ static int hpsbpkt_thread(void *__hi) { - struct sk_buff *skb; - struct hpsb_packet *packet; - void (*complete_routine)(void*); - void *complete_data; - - current->flags |= PF_NOFREEZE; + struct hpsb_packet *packet, *p; + struct list_head tmp; + int may_schedule; while (!kthread_should_stop()) { - while ((skb = skb_dequeue(&hpsbpkt_queue)) != NULL) { - packet = (struct hpsb_packet *)skb->data; - - complete_routine = packet->complete_routine; - complete_data = packet->complete_data; - packet->complete_routine = packet->complete_data = NULL; + INIT_LIST_HEAD(&tmp); + spin_lock_irq(&pending_packets_lock); + list_splice_init(&hpsbpkt_queue, &tmp); + spin_unlock_irq(&pending_packets_lock); - complete_routine(complete_data); + list_for_each_entry_safe(packet, p, &tmp, queue) { + list_del_init(&packet->queue); + packet->complete_routine(packet->complete_data); } set_current_state(TASK_INTERRUPTIBLE); - if (!skb_peek(&hpsbpkt_queue)) + spin_lock_irq(&pending_packets_lock); + may_schedule = list_empty(&hpsbpkt_queue); + spin_unlock_irq(&pending_packets_lock); + if (may_schedule) schedule(); __set_current_state(TASK_RUNNING); } @@ -1154,8 +1156,6 @@ static int __init ieee1394_init(void) { int i, ret; - skb_queue_head_init(&hpsbpkt_queue); - /* non-fatal error */ if (hpsb_init_config_roms()) { HPSB_ERR("Failed to initialize some config rom entries.\n"); @@ -1310,7 +1310,6 @@ EXPORT_SYMBOL(hpsb_make_streampacket); EXPORT_SYMBOL(hpsb_make_lockpacket); EXPORT_SYMBOL(hpsb_make_lock64packet); EXPORT_SYMBOL(hpsb_make_phypacket); -EXPORT_SYMBOL(hpsb_make_isopacket); EXPORT_SYMBOL(hpsb_read); EXPORT_SYMBOL(hpsb_write); EXPORT_SYMBOL(hpsb_packet_success); @@ -1321,15 +1320,12 @@ EXPORT_SYMBOL(hpsb_unregister_highlevel); EXPORT_SYMBOL(hpsb_register_addrspace); EXPORT_SYMBOL(hpsb_unregister_addrspace); EXPORT_SYMBOL(hpsb_allocate_and_register_addrspace); -EXPORT_SYMBOL(hpsb_listen_channel); -EXPORT_SYMBOL(hpsb_unlisten_channel); EXPORT_SYMBOL(hpsb_get_hostinfo); EXPORT_SYMBOL(hpsb_create_hostinfo); EXPORT_SYMBOL(hpsb_destroy_hostinfo); EXPORT_SYMBOL(hpsb_set_hostinfo_key); EXPORT_SYMBOL(hpsb_get_hostinfo_bykey); EXPORT_SYMBOL(hpsb_set_hostinfo); -EXPORT_SYMBOL(highlevel_host_reset); /** nodemgr.c **/ EXPORT_SYMBOL(hpsb_node_fill_packet); @@ -1372,11 +1368,10 @@ EXPORT_SYMBOL(hpsb_iso_wake); EXPORT_SYMBOL(hpsb_iso_recv_flush); /** csr1212.c **/ -EXPORT_SYMBOL(csr1212_new_directory); EXPORT_SYMBOL(csr1212_attach_keyval_to_directory); EXPORT_SYMBOL(csr1212_detach_keyval_from_directory); -EXPORT_SYMBOL(csr1212_release_keyval); -EXPORT_SYMBOL(csr1212_read); +EXPORT_SYMBOL(csr1212_get_keyval); +EXPORT_SYMBOL(csr1212_new_directory); EXPORT_SYMBOL(csr1212_parse_keyval); -EXPORT_SYMBOL(_csr1212_read_keyval); -EXPORT_SYMBOL(_csr1212_destroy_keyval); +EXPORT_SYMBOL(csr1212_read); +EXPORT_SYMBOL(csr1212_release_keyval);