⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 guid.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
字号:
/* * IEEE 1394 for Linux * * GUID collection and management * * Copyright (C) 2000 Andreas E. Bombe * * This code is licensed under the GPL.  See the file COPYING in the root * directory of the kernel sources for details. */#include <linux/kernel.h>#include <linux/list.h>#include <linux/slab.h>#include <asm/byteorder.h>#include <asm/atomic.h>#include "ieee1394_types.h"#include "ieee1394.h"#include "hosts.h"#include "ieee1394_transactions.h"#include "highlevel.h"#include "csr.h"static atomic_t outstanding_requests;static LIST_HEAD(guid_list);rwlock_t guid_lock = RW_LOCK_UNLOCKED;struct guid_entry {        struct list_head list;        atomic_t refcount;        u64 guid;        struct hpsb_host *host;        nodeid_t node_id;                atomic_t generation;};struct guid_req {        struct hpsb_packet *pkt;        struct tq_struct tq;};static struct guid_entry *create_guid_entry(void){        struct guid_entry *ge;        unsigned long flags;        ge = kmalloc(sizeof(struct guid_entry), SLAB_ATOMIC);        if (!ge) return NULL;        INIT_LIST_HEAD(&ge->list);        atomic_set(&ge->refcount, 0);        ge->guid = (u64) -1;        ge->host = NULL;        ge->node_id = 0;        atomic_set(&ge->generation, -1);        write_lock_irqsave(&guid_lock, flags);        list_add_tail(&ge->list, &guid_list);        write_unlock_irqrestore(&guid_lock, flags);        return ge;}static struct guid_entry *find_entry(u64 guid){        struct list_head *lh;        struct guid_entry *ge;                lh = guid_list.next;        while (lh != &guid_list) {                ge = list_entry(lh, struct guid_entry, list);                if (ge->guid == guid) return ge;                lh = lh->next;        }        return NULL;}static void associate_guid(struct hpsb_host *host, nodeid_t nodeid, u64 guid){        struct guid_entry *ge;        unsigned long flags;        HPSB_DEBUG("node %d on host 0x%p has GUID 0x%08x%08x",                   nodeid & NODE_MASK, host, (unsigned int)(guid >> 32),                   (unsigned int)(guid & 0xffffffff));        read_lock_irqsave(&guid_lock, flags);        ge = find_entry(guid);        read_unlock_irqrestore(&guid_lock, flags);        if (!ge) ge = create_guid_entry();        if (!ge) return;        ge->host = host;        ge->node_id = nodeid;        ge->guid = guid;        atomic_set(&ge->generation, get_hpsb_generation());}static void pkt_complete(struct guid_req *req){        struct hpsb_packet *pkt = req->pkt;        int rcode = (pkt->header[1] >> 12) & 0xf;        if (pkt->ack_code == ACK_PENDING && rcode == RCODE_COMPLETE) {                if (*(char *)pkt->data > 1) {                        associate_guid(pkt->host, pkt->node_id,                                       ((u64)be32_to_cpu(pkt->data[3]) << 32)                                       | be32_to_cpu(pkt->data[4]));                } else {                        HPSB_DEBUG("minimal ROM on node %d",                                   pkt->node_id & NODE_MASK);                }        } else {                HPSB_DEBUG("guid transaction error: ack %d, rcode %d",                           pkt->ack_code, rcode);        }        free_tlabel(pkt->host, pkt->node_id, pkt->tlabel);        free_hpsb_packet(pkt);        kfree(req);        if (atomic_dec_and_test(&outstanding_requests)) {                /* FIXME: free unreferenced and inactive GUID entries. */        }}static void host_reset(struct hpsb_host *host){        struct guid_req *greq;        struct hpsb_packet *pkt;        struct selfid *sid = (struct selfid *)host->topology_map;        int nodecount = host->node_count;        nodeid_t nodeid = LOCAL_BUS;        for (; nodecount; nodecount--, nodeid++, sid++) {                while (sid->extended) sid++;                if (!sid->link_active) continue;                if (nodeid == host->node_id) continue;                greq = kmalloc(sizeof(struct guid_req), SLAB_ATOMIC);                if (!greq) {                        HPSB_ERR("out of memory in GUID processing");                        return;                }                pkt = hpsb_make_readbpacket(host, nodeid,                                            CSR_REGISTER_BASE + CSR_CONFIG_ROM,                                            20);                if (!pkt) {                        kfree(greq);                        HPSB_ERR("out of memory in GUID processing");                        return;                }                INIT_LIST_HEAD(&greq->tq.list);                greq->tq.sync = 0;                greq->tq.routine = (void (*)(void*))pkt_complete;                greq->tq.data = greq;                greq->pkt = pkt;                queue_task(&greq->tq, &pkt->complete_tq);                if (!hpsb_send_packet(pkt)) {                        free_tlabel(pkt->host, pkt->node_id, pkt->tlabel);                        free_hpsb_packet(pkt);                        kfree(greq);                        HPSB_NOTICE("failed to send packet in GUID processing");                }                HPSB_INFO("GUID request sent to node %d", nodeid & NODE_MASK);                atomic_inc(&outstanding_requests);        }}struct guid_entry *hpsb_guid_get_handle(u64 guid){        unsigned long flags;        struct guid_entry *ge;        read_lock_irqsave(&guid_lock, flags);        ge = find_entry(guid);        if (ge) atomic_inc(&ge->refcount);        read_unlock_irqrestore(&guid_lock, flags);        return ge;}struct hpsb_host *hpsb_guid_localhost(struct guid_entry *ge){        if (atomic_read(&ge->generation) != get_hpsb_generation()) return NULL;        if (ge->node_id == ge->host->node_id) return ge->host;        return NULL;}int hpsb_guid_fill_packet(struct guid_entry *ge, struct hpsb_packet *pkt){        if (atomic_read(&ge->generation) != get_hpsb_generation()) return 0;        pkt->host = ge->host;        pkt->node_id = ge->node_id;        pkt->generation = atomic_read(&ge->generation);        return 1;}static struct hpsb_highlevel_ops guid_ops = {        host_reset:  host_reset,};void init_ieee1394_guid(void){        atomic_set(&outstanding_requests, 0);        if (!hpsb_register_highlevel("GUID manager", &guid_ops)) {                HPSB_ERR("out of memory during ieee1394 initialization");        }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -