summaryrefslogtreecommitdiff
path: root/net/sctp/stream_sched.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp/stream_sched.c')
-rw-r--r--net/sctp/stream_sched.c82
1 files changed, 37 insertions, 45 deletions
diff --git a/net/sctp/stream_sched.c b/net/sctp/stream_sched.c
index a6c04a94b08f..50f8b5240359 100644
--- a/net/sctp/stream_sched.c
+++ b/net/sctp/stream_sched.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
/* SCTP kernel implementation
* (C) Copyright Red Hat Inc. 2017
*
@@ -5,22 +6,6 @@
*
* These functions manipulate sctp stream queue/scheduling.
*
- * This SCTP implementation is free software;
- * you can redistribute it and/or modify it under the terms of
- * the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This SCTP implementation is distributed in the hope that it
- * will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * ************************
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with GNU CC; see the file COPYING. If not, see
- * <http://www.gnu.org/licenses/>.
- *
* Please send any bug reports or fixes you make to the
* email addresched(es):
* lksctp developers <linux-sctp@vger.kernel.org>
@@ -61,7 +46,7 @@ static int sctp_sched_fcfs_init_sid(struct sctp_stream *stream, __u16 sid,
return 0;
}
-static void sctp_sched_fcfs_free(struct sctp_stream *stream)
+static void sctp_sched_fcfs_free_sid(struct sctp_stream *stream, __u16 sid)
{
}
@@ -106,12 +91,12 @@ static void sctp_sched_fcfs_unsched_all(struct sctp_stream *stream)
{
}
-static struct sctp_sched_ops sctp_sched_fcfs = {
+static const struct sctp_sched_ops sctp_sched_fcfs = {
.set = sctp_sched_fcfs_set,
.get = sctp_sched_fcfs_get,
.init = sctp_sched_fcfs_init,
.init_sid = sctp_sched_fcfs_init_sid,
- .free = sctp_sched_fcfs_free,
+ .free_sid = sctp_sched_fcfs_free_sid,
.enqueue = sctp_sched_fcfs_enqueue,
.dequeue = sctp_sched_fcfs_dequeue,
.dequeue_done = sctp_sched_fcfs_dequeue_done,
@@ -126,10 +111,10 @@ static void sctp_sched_ops_fcfs_init(void)
/* API to other parts of the stack */
-static struct sctp_sched_ops *sctp_sched_ops[SCTP_SS_MAX + 1];
+static const struct sctp_sched_ops *sctp_sched_ops[SCTP_SS_MAX + 1];
void sctp_sched_ops_register(enum sctp_sched_type sched,
- struct sctp_sched_ops *sched_ops)
+ const struct sctp_sched_ops *sched_ops)
{
sctp_sched_ops[sched] = sched_ops;
}
@@ -139,38 +124,45 @@ void sctp_sched_ops_init(void)
sctp_sched_ops_fcfs_init();
sctp_sched_ops_prio_init();
sctp_sched_ops_rr_init();
+ sctp_sched_ops_fc_init();
+ sctp_sched_ops_wfq_init();
+}
+
+static void sctp_sched_free_sched(struct sctp_stream *stream)
+{
+ const struct sctp_sched_ops *sched = sctp_sched_ops_from_stream(stream);
+ struct sctp_stream_out_ext *soute;
+ int i;
+
+ sched->unsched_all(stream);
+ for (i = 0; i < stream->outcnt; i++) {
+ soute = SCTP_SO(stream, i)->ext;
+ if (!soute)
+ continue;
+ sched->free_sid(stream, i);
+ /* Give the next scheduler a clean slate. */
+ memset_after(soute, 0, outq);
+ }
}
int sctp_sched_set_sched(struct sctp_association *asoc,
enum sctp_sched_type sched)
{
- struct sctp_sched_ops *n = sctp_sched_ops[sched];
- struct sctp_sched_ops *old = asoc->outqueue.sched;
+ const struct sctp_sched_ops *old = asoc->outqueue.sched;
struct sctp_datamsg *msg = NULL;
+ const struct sctp_sched_ops *n;
struct sctp_chunk *ch;
int i, ret = 0;
- if (old == n)
- return ret;
-
if (sched > SCTP_SS_MAX)
return -EINVAL;
- if (old) {
- old->free(&asoc->stream);
-
- /* Give the next scheduler a clean slate. */
- for (i = 0; i < asoc->stream.outcnt; i++) {
- void *p = SCTP_SO(&asoc->stream, i)->ext;
-
- if (!p)
- continue;
+ n = sctp_sched_ops[sched];
+ if (old == n)
+ return ret;
- p += offsetofend(struct sctp_stream_out_ext, outq);
- memset(p, 0, sizeof(struct sctp_stream_out_ext) -
- offsetofend(struct sctp_stream_out_ext, outq));
- }
- }
+ if (old)
+ sctp_sched_free_sched(&asoc->stream);
asoc->outqueue.sched = n;
n->init(&asoc->stream);
@@ -178,7 +170,7 @@ int sctp_sched_set_sched(struct sctp_association *asoc,
if (!SCTP_SO(&asoc->stream, i)->ext)
continue;
- ret = n->init_sid(&asoc->stream, i, GFP_KERNEL);
+ ret = n->init_sid(&asoc->stream, i, GFP_ATOMIC);
if (ret)
goto err;
}
@@ -194,7 +186,7 @@ int sctp_sched_set_sched(struct sctp_association *asoc,
return ret;
err:
- n->free(&asoc->stream);
+ sctp_sched_free_sched(&asoc->stream);
asoc->outqueue.sched = &sctp_sched_fcfs; /* Always safe */
return ret;
@@ -243,7 +235,7 @@ int sctp_sched_get_value(struct sctp_association *asoc, __u16 sid,
void sctp_sched_dequeue_done(struct sctp_outq *q, struct sctp_chunk *ch)
{
if (!list_is_last(&ch->frag_list, &ch->msg->chunks) &&
- !q->asoc->intl_enable) {
+ !q->asoc->peer.intl_capable) {
struct sctp_stream_out *sout;
__u16 sid;
@@ -271,14 +263,14 @@ void sctp_sched_dequeue_common(struct sctp_outq *q, struct sctp_chunk *ch)
int sctp_sched_init_sid(struct sctp_stream *stream, __u16 sid, gfp_t gfp)
{
- struct sctp_sched_ops *sched = sctp_sched_ops_from_stream(stream);
+ const struct sctp_sched_ops *sched = sctp_sched_ops_from_stream(stream);
struct sctp_stream_out_ext *ext = SCTP_SO(stream, sid)->ext;
INIT_LIST_HEAD(&ext->outq);
return sched->init_sid(stream, sid, gfp);
}
-struct sctp_sched_ops *sctp_sched_ops_from_stream(struct sctp_stream *stream)
+const struct sctp_sched_ops *sctp_sched_ops_from_stream(struct sctp_stream *stream)
{
struct sctp_association *asoc;