Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
41a63406
Commit
41a63406
authored
Aug 20, 2015
by
Ben Skeggs
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drm/nouveau/nvif: return min/max versions for supported object classes
Signed-off-by:
Ben Skeggs
<
bskeggs@redhat.com
>
parent
f58ddf95
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
92 additions
and
42 deletions
+92
-42
drivers/gpu/drm/nouveau/include/nvif/ioctl.h
drivers/gpu/drm/nouveau/include/nvif/ioctl.h
+5
-1
drivers/gpu/drm/nouveau/include/nvif/object.h
drivers/gpu/drm/nouveau/include/nvif/object.h
+8
-1
drivers/gpu/drm/nouveau/include/nvkm/core/parent.h
drivers/gpu/drm/nouveau/include/nvkm/core/parent.h
+1
-1
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
+11
-10
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drm.c
+6
-5
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nv50_display.c
+7
-6
drivers/gpu/drm/nouveau/nvif/object.c
drivers/gpu/drm/nouveau/nvif/object.c
+40
-13
drivers/gpu/drm/nouveau/nvkm/core/parent.c
drivers/gpu/drm/nouveau/nvkm/core/parent.c
+14
-5
No files found.
drivers/gpu/drm/nouveau/include/nvif/ioctl.h
View file @
41a63406
...
@@ -40,7 +40,11 @@ struct nvif_ioctl_sclass_v0 {
...
@@ -40,7 +40,11 @@ struct nvif_ioctl_sclass_v0 {
__u8
version
;
__u8
version
;
__u8
count
;
__u8
count
;
__u8
pad02
[
6
];
__u8
pad02
[
6
];
__s32
oclass
[];
struct
nvif_ioctl_sclass_oclass_v0
{
__s32
oclass
;
__s16
minver
;
__s16
maxver
;
}
oclass
[];
};
};
struct
nvif_ioctl_new_v0
{
struct
nvif_ioctl_new_v0
{
...
...
drivers/gpu/drm/nouveau/include/nvif/object.h
View file @
41a63406
...
@@ -3,6 +3,12 @@
...
@@ -3,6 +3,12 @@
#include <nvif/os.h>
#include <nvif/os.h>
struct
nvif_sclass
{
s32
oclass
;
int
minver
;
int
maxver
;
};
struct
nvif_object
{
struct
nvif_object
{
struct
nvif_client
*
client
;
struct
nvif_client
*
client
;
u32
handle
;
u32
handle
;
...
@@ -18,7 +24,8 @@ int nvif_object_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32,
...
@@ -18,7 +24,8 @@ int nvif_object_init(struct nvif_object *, u32 handle, s32 oclass, void *, u32,
struct
nvif_object
*
);
struct
nvif_object
*
);
void
nvif_object_fini
(
struct
nvif_object
*
);
void
nvif_object_fini
(
struct
nvif_object
*
);
int
nvif_object_ioctl
(
struct
nvif_object
*
,
void
*
,
u32
,
void
**
);
int
nvif_object_ioctl
(
struct
nvif_object
*
,
void
*
,
u32
,
void
**
);
int
nvif_object_sclass
(
struct
nvif_object
*
,
s32
*
,
int
);
int
nvif_object_sclass_get
(
struct
nvif_object
*
,
struct
nvif_sclass
**
);
void
nvif_object_sclass_put
(
struct
nvif_sclass
**
);
u32
nvif_object_rd
(
struct
nvif_object
*
,
int
,
u64
);
u32
nvif_object_rd
(
struct
nvif_object
*
,
int
,
u64
);
void
nvif_object_wr
(
struct
nvif_object
*
,
int
,
u64
,
u32
);
void
nvif_object_wr
(
struct
nvif_object
*
,
int
,
u64
,
u32
);
int
nvif_object_mthd
(
struct
nvif_object
*
,
u32
,
void
*
,
u32
);
int
nvif_object_mthd
(
struct
nvif_object
*
,
u32
,
void
*
,
u32
);
...
...
drivers/gpu/drm/nouveau/include/nvkm/core/parent.h
View file @
41a63406
...
@@ -47,5 +47,5 @@ void _nvkm_parent_dtor(struct nvkm_object *);
...
@@ -47,5 +47,5 @@ void _nvkm_parent_dtor(struct nvkm_object *);
int
nvkm_parent_sclass
(
struct
nvkm_object
*
,
s32
handle
,
int
nvkm_parent_sclass
(
struct
nvkm_object
*
,
s32
handle
,
struct
nvkm_object
**
pengine
,
struct
nvkm_object
**
pengine
,
struct
nvkm_oclass
**
poclass
);
struct
nvkm_oclass
**
poclass
);
int
nvkm_parent_lclass
(
struct
nvkm_object
*
,
s32
*
,
int
);
int
nvkm_parent_lclass
(
struct
nvkm_object
*
,
void
*
,
int
);
#endif
#endif
drivers/gpu/drm/nouveau/nouveau_abi16.c
View file @
41a63406
...
@@ -369,7 +369,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
...
@@ -369,7 +369,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
struct
nouveau_abi16_chan
*
chan
;
struct
nouveau_abi16_chan
*
chan
;
struct
nouveau_abi16_ntfy
*
ntfy
;
struct
nouveau_abi16_ntfy
*
ntfy
;
struct
nvif_client
*
client
;
struct
nvif_client
*
client
;
u32
sclass
[
32
]
;
struct
nvif_sclass
*
sclass
;
s32
oclass
=
0
;
s32
oclass
=
0
;
int
ret
,
i
;
int
ret
,
i
;
...
@@ -384,19 +384,19 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
...
@@ -384,19 +384,19 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
if
(
!
chan
)
if
(
!
chan
)
return
nouveau_abi16_put
(
abi16
,
-
ENOENT
);
return
nouveau_abi16_put
(
abi16
,
-
ENOENT
);
ret
=
nvif_object_sclass
(
&
chan
->
chan
->
user
,
sclass
,
ARRAY_SIZE
(
sclass
)
);
ret
=
nvif_object_sclass
_get
(
&
chan
->
chan
->
user
,
&
sclass
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
nouveau_abi16_put
(
abi16
,
ret
);
return
nouveau_abi16_put
(
abi16
,
ret
);
if
((
init
->
class
&
0x00ff
)
==
0x006e
)
{
if
((
init
->
class
&
0x00ff
)
==
0x006e
)
{
/* nvsw: compatibility with older 0x*6e class identifier */
/* nvsw: compatibility with older 0x*6e class identifier */
for
(
i
=
0
;
!
oclass
&&
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
!
oclass
&&
i
<
ret
;
i
++
)
{
switch
(
sclass
[
i
])
{
switch
(
sclass
[
i
]
.
oclass
)
{
case
NVIF_IOCTL_NEW_V0_SW_NV04
:
case
NVIF_IOCTL_NEW_V0_SW_NV04
:
case
NVIF_IOCTL_NEW_V0_SW_NV10
:
case
NVIF_IOCTL_NEW_V0_SW_NV10
:
case
NVIF_IOCTL_NEW_V0_SW_NV50
:
case
NVIF_IOCTL_NEW_V0_SW_NV50
:
case
NVIF_IOCTL_NEW_V0_SW_GF100
:
case
NVIF_IOCTL_NEW_V0_SW_GF100
:
oclass
=
sclass
[
i
];
oclass
=
sclass
[
i
]
.
oclass
;
break
;
break
;
default:
default:
break
;
break
;
...
@@ -406,8 +406,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
...
@@ -406,8 +406,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
if
((
init
->
class
&
0x00ff
)
==
0x00b1
)
{
if
((
init
->
class
&
0x00ff
)
==
0x00b1
)
{
/* msvld: compatibility with incorrect version exposure */
/* msvld: compatibility with incorrect version exposure */
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
if
((
sclass
[
i
]
&
0x00ff
)
==
0x00b1
)
{
if
((
sclass
[
i
]
.
oclass
&
0x00ff
)
==
0x00b1
)
{
oclass
=
sclass
[
i
];
oclass
=
sclass
[
i
]
.
oclass
;
break
;
break
;
}
}
}
}
...
@@ -415,8 +415,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
...
@@ -415,8 +415,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
if
((
init
->
class
&
0x00ff
)
==
0x00b2
)
{
/* mspdec */
if
((
init
->
class
&
0x00ff
)
==
0x00b2
)
{
/* mspdec */
/* mspdec: compatibility with incorrect version exposure */
/* mspdec: compatibility with incorrect version exposure */
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
if
((
sclass
[
i
]
&
0x00ff
)
==
0x00b2
)
{
if
((
sclass
[
i
]
.
oclass
&
0x00ff
)
==
0x00b2
)
{
oclass
=
sclass
[
i
];
oclass
=
sclass
[
i
]
.
oclass
;
break
;
break
;
}
}
}
}
...
@@ -424,8 +424,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
...
@@ -424,8 +424,8 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
if
((
init
->
class
&
0x00ff
)
==
0x00b3
)
{
/* msppp */
if
((
init
->
class
&
0x00ff
)
==
0x00b3
)
{
/* msppp */
/* msppp: compatibility with incorrect version exposure */
/* msppp: compatibility with incorrect version exposure */
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
for
(
i
=
0
;
i
<
ret
;
i
++
)
{
if
((
sclass
[
i
]
&
0x00ff
)
==
0x00b3
)
{
if
((
sclass
[
i
]
.
oclass
&
0x00ff
)
==
0x00b3
)
{
oclass
=
sclass
[
i
];
oclass
=
sclass
[
i
]
.
oclass
;
break
;
break
;
}
}
}
}
...
@@ -433,6 +433,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
...
@@ -433,6 +433,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
oclass
=
init
->
class
;
oclass
=
init
->
class
;
}
}
nvif_object_sclass_put
(
&
sclass
);
if
(
!
oclass
)
if
(
!
oclass
)
return
nouveau_abi16_put
(
abi16
,
-
EINVAL
);
return
nouveau_abi16_put
(
abi16
,
-
EINVAL
);
...
...
drivers/gpu/drm/nouveau/nouveau_drm.c
View file @
41a63406
...
@@ -152,9 +152,9 @@ static void
...
@@ -152,9 +152,9 @@ static void
nouveau_accel_init
(
struct
nouveau_drm
*
drm
)
nouveau_accel_init
(
struct
nouveau_drm
*
drm
)
{
{
struct
nvif_device
*
device
=
&
drm
->
device
;
struct
nvif_device
*
device
=
&
drm
->
device
;
struct
nvif_sclass
*
sclass
;
u32
arg0
,
arg1
;
u32
arg0
,
arg1
;
s32
sclass
[
16
];
int
ret
,
i
,
n
;
int
ret
,
i
;
if
(
nouveau_noaccel
)
if
(
nouveau_noaccel
)
return
;
return
;
...
@@ -163,12 +163,12 @@ nouveau_accel_init(struct nouveau_drm *drm)
...
@@ -163,12 +163,12 @@ nouveau_accel_init(struct nouveau_drm *drm)
/*XXX: this is crap, but the fence/channel stuff is a little
/*XXX: this is crap, but the fence/channel stuff is a little
* backwards in some places. this will be fixed.
* backwards in some places. this will be fixed.
*/
*/
ret
=
n
vif_object_sclass
(
&
device
->
object
,
sclass
,
ARRAY_SIZE
(
sclass
)
);
ret
=
n
=
nvif_object_sclass_get
(
&
device
->
object
,
&
sclass
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
;
return
;
for
(
ret
=
-
ENOSYS
,
i
=
0
;
ret
&&
i
<
ARRAY_SIZE
(
sclass
)
;
i
++
)
{
for
(
ret
=
-
ENOSYS
,
i
=
0
;
i
<
n
;
i
++
)
{
switch
(
sclass
[
i
])
{
switch
(
sclass
[
i
]
.
oclass
)
{
case
NV03_CHANNEL_DMA
:
case
NV03_CHANNEL_DMA
:
ret
=
nv04_fence_create
(
drm
);
ret
=
nv04_fence_create
(
drm
);
break
;
break
;
...
@@ -195,6 +195,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
...
@@ -195,6 +195,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
}
}
}
}
nvif_object_sclass_put
(
&
sclass
);
if
(
ret
)
{
if
(
ret
)
{
NV_ERROR
(
drm
,
"failed to initialise sync subsystem, %d
\n
"
,
ret
);
NV_ERROR
(
drm
,
"failed to initialise sync subsystem, %d
\n
"
,
ret
);
nouveau_accel_fini
(
drm
);
nouveau_accel_fini
(
drm
);
...
...
drivers/gpu/drm/nouveau/nv50_display.c
View file @
41a63406
...
@@ -69,29 +69,30 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp,
...
@@ -69,29 +69,30 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp,
struct
nv50_chan
*
chan
)
struct
nv50_chan
*
chan
)
{
{
const
u32
handle
=
(
oclass
[
0
]
<<
16
)
|
head
;
const
u32
handle
=
(
oclass
[
0
]
<<
16
)
|
head
;
s
32
sclass
[
8
]
;
s
truct
nvif_sclass
*
sclass
;
int
ret
,
i
;
int
ret
,
i
,
n
;
chan
->
device
=
device
;
chan
->
device
=
device
;
ret
=
nvif_object_sclass
(
disp
,
sclass
,
ARRAY_SIZE
(
sclass
));
ret
=
n
=
nvif_object_sclass_get
(
disp
,
&
sclass
);
WARN_ON
(
ret
>
ARRAY_SIZE
(
sclass
));
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
while
(
oclass
[
0
])
{
while
(
oclass
[
0
])
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
sclass
)
;
i
++
)
{
for
(
i
=
0
;
i
<
n
;
i
++
)
{
if
(
sclass
[
i
]
==
oclass
[
0
])
{
if
(
sclass
[
i
]
.
oclass
==
oclass
[
0
])
{
ret
=
nvif_object_init
(
disp
,
handle
,
oclass
[
0
],
ret
=
nvif_object_init
(
disp
,
handle
,
oclass
[
0
],
data
,
size
,
&
chan
->
user
);
data
,
size
,
&
chan
->
user
);
if
(
ret
==
0
)
if
(
ret
==
0
)
nvif_object_map
(
&
chan
->
user
);
nvif_object_map
(
&
chan
->
user
);
nvif_object_sclass_put
(
&
sclass
);
return
ret
;
return
ret
;
}
}
}
}
oclass
++
;
oclass
++
;
}
}
nvif_object_sclass_put
(
&
sclass
);
return
-
ENOSYS
;
return
-
ENOSYS
;
}
}
...
...
drivers/gpu/drm/nouveau/nvif/object.c
View file @
41a63406
...
@@ -48,26 +48,53 @@ nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
...
@@ -48,26 +48,53 @@ nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
data
,
size
,
hack
);
data
,
size
,
hack
);
}
}
void
nvif_object_sclass_put
(
struct
nvif_sclass
**
psclass
)
{
kfree
(
*
psclass
);
*
psclass
=
NULL
;
}
int
int
nvif_object_sclass
(
struct
nvif_object
*
object
,
s32
*
oclass
,
int
count
)
nvif_object_sclass
_get
(
struct
nvif_object
*
object
,
struct
nvif_sclass
**
psclass
)
{
{
struct
{
struct
{
struct
nvif_ioctl_v0
ioctl
;
struct
nvif_ioctl_v0
ioctl
;
struct
nvif_ioctl_sclass_v0
sclass
;
struct
nvif_ioctl_sclass_v0
sclass
;
}
*
args
;
}
*
args
=
NULL
;
u32
size
=
count
*
sizeof
(
args
->
sclass
.
oclass
[
0
])
;
int
ret
,
cnt
=
0
,
i
;
int
ret
;
u32
size
;
if
(
!
(
args
=
kmalloc
(
sizeof
(
*
args
)
+
size
,
GFP_KERNEL
)))
while
(
1
)
{
return
-
ENOMEM
;
size
=
sizeof
(
*
args
)
+
cnt
*
sizeof
(
args
->
sclass
.
oclass
[
0
]);
args
->
ioctl
.
version
=
0
;
if
(
!
(
args
=
kmalloc
(
size
,
GFP_KERNEL
)))
args
->
ioctl
.
type
=
NVIF_IOCTL_V0_SCLASS
;
return
-
ENOMEM
;
args
->
sclass
.
version
=
0
;
args
->
ioctl
.
version
=
0
;
args
->
sclass
.
count
=
count
;
args
->
ioctl
.
type
=
NVIF_IOCTL_V0_SCLASS
;
args
->
sclass
.
version
=
0
;
args
->
sclass
.
count
=
cnt
;
ret
=
nvif_object_ioctl
(
object
,
args
,
size
,
NULL
);
if
(
ret
==
0
&&
args
->
sclass
.
count
<=
cnt
)
break
;
cnt
=
args
->
sclass
.
count
;
kfree
(
args
);
if
(
ret
!=
0
)
return
ret
;
}
*
psclass
=
kzalloc
(
sizeof
(
**
psclass
)
*
args
->
sclass
.
count
,
GFP_KERNEL
);
if
(
*
psclass
)
{
for
(
i
=
0
;
i
<
args
->
sclass
.
count
;
i
++
)
{
(
*
psclass
)[
i
].
oclass
=
args
->
sclass
.
oclass
[
i
].
oclass
;
(
*
psclass
)[
i
].
minver
=
args
->
sclass
.
oclass
[
i
].
minver
;
(
*
psclass
)[
i
].
maxver
=
args
->
sclass
.
oclass
[
i
].
maxver
;
}
ret
=
args
->
sclass
.
count
;
}
else
{
ret
=
-
ENOMEM
;
}
ret
=
nvif_object_ioctl
(
object
,
args
,
sizeof
(
*
args
)
+
size
,
NULL
);
ret
=
ret
?
ret
:
args
->
sclass
.
count
;
memcpy
(
oclass
,
args
->
sclass
.
oclass
,
size
);
kfree
(
args
);
kfree
(
args
);
return
ret
;
return
ret
;
}
}
...
...
drivers/gpu/drm/nouveau/nvkm/core/parent.c
View file @
41a63406
...
@@ -25,6 +25,8 @@
...
@@ -25,6 +25,8 @@
#include <core/client.h>
#include <core/client.h>
#include <core/engine.h>
#include <core/engine.h>
#include <nvif/ioctl.h>
int
int
nvkm_parent_sclass
(
struct
nvkm_object
*
parent
,
s32
handle
,
nvkm_parent_sclass
(
struct
nvkm_object
*
parent
,
s32
handle
,
struct
nvkm_object
**
pengine
,
struct
nvkm_object
**
pengine
,
...
@@ -66,8 +68,9 @@ nvkm_parent_sclass(struct nvkm_object *parent, s32 handle,
...
@@ -66,8 +68,9 @@ nvkm_parent_sclass(struct nvkm_object *parent, s32 handle,
}
}
int
int
nvkm_parent_lclass
(
struct
nvkm_object
*
parent
,
s32
*
lclass
,
int
size
)
nvkm_parent_lclass
(
struct
nvkm_object
*
parent
,
void
*
data
,
int
size
)
{
{
struct
nvif_ioctl_sclass_oclass_v0
*
lclass
=
data
;
struct
nvkm_oclass
*
sclass
,
*
oclass
;
struct
nvkm_oclass
*
sclass
,
*
oclass
;
struct
nvkm_engine
*
engine
;
struct
nvkm_engine
*
engine
;
int
nr
=
-
1
,
i
;
int
nr
=
-
1
,
i
;
...
@@ -75,8 +78,11 @@ nvkm_parent_lclass(struct nvkm_object *parent, s32 *lclass, int size)
...
@@ -75,8 +78,11 @@ nvkm_parent_lclass(struct nvkm_object *parent, s32 *lclass, int size)
sclass
=
nv_parent
(
parent
)
->
sclass
;
sclass
=
nv_parent
(
parent
)
->
sclass
;
while
((
oclass
=
sclass
++
)
&&
oclass
->
ofuncs
)
{
while
((
oclass
=
sclass
++
)
&&
oclass
->
ofuncs
)
{
if
(
++
nr
<
size
)
if
(
++
nr
<
size
)
{
lclass
[
nr
]
=
oclass
->
handle
;
lclass
[
nr
].
oclass
=
oclass
->
handle
;
lclass
[
nr
].
minver
=
-
2
;
lclass
[
nr
].
maxver
=
-
2
;
}
}
}
mask
=
nv_parent
(
parent
)
->
engine
;
mask
=
nv_parent
(
parent
)
->
engine
;
...
@@ -84,8 +90,11 @@ nvkm_parent_lclass(struct nvkm_object *parent, s32 *lclass, int size)
...
@@ -84,8 +90,11 @@ nvkm_parent_lclass(struct nvkm_object *parent, s32 *lclass, int size)
engine
=
nvkm_engine
(
parent
,
i
);
engine
=
nvkm_engine
(
parent
,
i
);
if
(
engine
&&
(
oclass
=
engine
->
sclass
))
{
if
(
engine
&&
(
oclass
=
engine
->
sclass
))
{
while
(
oclass
->
ofuncs
)
{
while
(
oclass
->
ofuncs
)
{
if
(
++
nr
<
size
)
if
(
++
nr
<
size
)
{
lclass
[
nr
]
=
oclass
->
handle
;
lclass
[
nr
].
oclass
=
oclass
->
handle
;
lclass
[
nr
].
minver
=
-
2
;
lclass
[
nr
].
maxver
=
-
2
;
}
oclass
++
;
oclass
++
;
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment