blob: ff61cc8a56bd8bf70ea8df634b8e2fca0d201ce1 [file] [log] [blame]
developer5d86c142023-12-06 14:18:27 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
4 *
5 * Author: Frank-zj Lin <frank-zj.lin@mediatek.com>
6 */
7
8#include <linux/hashtable.h>
9#include <linux/spinlock.h>
10#include <linux/slab.h>
11
12#include <net/pptp.h>
13
14#include "tops/hwspinlock.h"
15#include "tops/seq_gen.h"
16
17#define PPTP_SEQ_HT_BITS 4
18
19struct pptp_seq {
20 struct hlist_node hlist;
21 int seq_gen_idx;
22 uint16_t call_id;
23};
24
25static DEFINE_HASHTABLE(pptp_seq_ht, PPTP_SEQ_HT_BITS);
26static DEFINE_SPINLOCK(pptp_seq_ht_lock);
27
28static struct pptp_seq *mtk_tops_pptp_seq_find_no_lock(uint16_t call_id)
29{
30 struct pptp_seq *pptp_seq;
31
32 hash_for_each_possible(pptp_seq_ht, pptp_seq, hlist, call_id) {
33 if (pptp_seq->call_id == call_id)
34 return pptp_seq;
35 }
36
37 return ERR_PTR(-ENODEV);
38}
39
40static int mtk_tops_pptp_seq_alloc_no_lock(uint16_t call_id, uint32_t seq_start,
41 int *seq_gen_idx)
42{
43 struct pptp_seq *pptp_seq;
44 int ret;
45
46 if (!IS_ERR(mtk_tops_pptp_seq_find_no_lock(call_id)))
47 return -EBUSY;
48
49 ret = mtk_tops_seq_gen_alloc(seq_gen_idx);
50 if (ret)
51 return ret;
52
53 pptp_seq = kzalloc(sizeof(struct pptp_seq), GFP_KERNEL);
54 if (!pptp_seq) {
55 mtk_tops_seq_gen_free(*seq_gen_idx);
56 return -ENOMEM;
57 }
58
59 pptp_seq->seq_gen_idx = *seq_gen_idx;
60 pptp_seq->call_id = call_id;
61 hash_add(pptp_seq_ht, &pptp_seq->hlist, pptp_seq->call_id);
62
63 mtk_tops_seq_gen_set_32(*seq_gen_idx, seq_start);
64
65 return 0;
66}
67
68int mtk_tops_pptp_seq_alloc(uint16_t call_id, uint32_t seq_start,
69 int *seq_gen_idx)
70{
71 unsigned long flag;
72 int ret;
73
74 spin_lock_irqsave(&pptp_seq_ht_lock, flag);
75
76 ret = mtk_tops_pptp_seq_alloc_no_lock(call_id, seq_start, seq_gen_idx);
77
78 spin_unlock_irqrestore(&pptp_seq_ht_lock, flag);
79
80 return ret;
81}
82
83static void mtk_tops_pptp_seq_free_no_lock(uint16_t call_id)
84{
85 struct pptp_seq *pptp_seq;
86
87 pptp_seq = mtk_tops_pptp_seq_find_no_lock(call_id);
88 if (IS_ERR(pptp_seq))
89 return;
90
91 mtk_tops_seq_gen_free(pptp_seq->seq_gen_idx);
92 hash_del(&pptp_seq->hlist);
93 kfree(pptp_seq);
94}
95
96void mtk_tops_pptp_seq_free(uint16_t call_id)
97{
98 unsigned long flag;
99
100 spin_lock_irqsave(&pptp_seq_ht_lock, flag);
101
102 mtk_tops_pptp_seq_free_no_lock(call_id);
103
104 spin_unlock_irqrestore(&pptp_seq_ht_lock, flag);
105}
106
107static int mtk_tops_pptp_seq_next_no_lock(uint16_t call_id, uint32_t *val)
108{
109 struct pptp_seq *pptp_seq;
110
111 pptp_seq = mtk_tops_pptp_seq_find_no_lock(call_id);
112 if (IS_ERR(pptp_seq))
113 return -EINVAL;
114
115 return mtk_tops_seq_gen_next_32(pptp_seq->seq_gen_idx, val);
116}
117
118static int mtk_tops_pptp_seq_next(uint16_t call_id, uint32_t *val)
119{
120 unsigned long flag;
121 int ret;
122
123 spin_lock_irqsave(&pptp_seq_ht_lock, flag);
124
125 mtk_tops_hwspin_lock(HWSPINLOCK_GROUP_CLUST,
126 HWSPINLOCK_CLUST_SLOT_PPTP_SEQ);
127
128 ret = mtk_tops_pptp_seq_next_no_lock(call_id, val);
129
130 mtk_tops_hwspin_unlock(HWSPINLOCK_GROUP_CLUST,
131 HWSPINLOCK_CLUST_SLOT_PPTP_SEQ);
132
133 spin_unlock_irqrestore(&pptp_seq_ht_lock, flag);
134
135 return ret;
136}
137
138static int mtk_tops_pptp_seq_get_seq_gen_idx_no_lock(uint16_t call_id,
139 int *seq_gen_idx)
140{
141 struct pptp_seq *pptp_seq;
142
143 pptp_seq = mtk_tops_pptp_seq_find_no_lock(call_id);
144 if (IS_ERR(pptp_seq))
145 return -EINVAL;
146
147 *seq_gen_idx = pptp_seq->seq_gen_idx;
148
149 return 0;
150}
151
152int mtk_tops_pptp_seq_get_seq_gen_idx(uint16_t call_id, int *seq_gen_idx)
153{
154 unsigned long flag;
155 int ret;
156
157 spin_lock_irqsave(&pptp_seq_ht_lock, flag);
158
159 ret = mtk_tops_pptp_seq_get_seq_gen_idx_no_lock(call_id, seq_gen_idx);
160
161 spin_unlock_irqrestore(&pptp_seq_ht_lock, flag);
162
163 return ret;
164}
165
166void mtk_tops_pptp_seq_init(void)
167{
168 mtk_pptp_seq_next = mtk_tops_pptp_seq_next;
169}
170
171void mtk_tops_pptp_seq_deinit(void)
172{
173 mtk_pptp_seq_next = NULL;
174}