Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
White Rabbit Switch - Software
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
86
Issues
86
List
Board
Labels
Milestones
Merge Requests
4
Merge Requests
4
CI / CD
CI / CD
Pipelines
Schedules
Wiki
Wiki
image/svg+xml
Discourse
Discourse
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Projects
White Rabbit Switch - Software
Commits
accbd802
Commit
accbd802
authored
Dec 19, 2010
by
Alessandro Rubini
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
misc code wrote on Dec 9th with Tom
parent
901772d6
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
136 additions
and
58 deletions
+136
-58
device.c
nic/device.c
+2
-0
nic-core.c
nic/nic-core.c
+35
-30
timestamp.c
nic/timestamp.c
+86
-23
wr-nic.h
nic/wr-nic.h
+13
-5
No files found.
nic/device.c
View file @
accbd802
...
...
@@ -190,6 +190,8 @@ static int __devinit wrn_probe(struct platform_device *pdev)
writel
(
NIC_CR_RX_EN
|
NIC_CR_TX_EN
,
&
wrn
->
regs
->
CR
);
writel
(
~
0
,
(
void
*
)
wrn
->
regs
+
0x24
/* EIC_IER */
);
printk
(
"imr: %08x
\n
"
,
readl
((
void
*
)
wrn
->
regs
+
0x28
/* EIC_IMR */
));
wrn_tstamp_init
(
wrn
);
err
=
0
;
out:
if
(
err
)
{
...
...
nic/nic-core.c
View file @
accbd802
...
...
@@ -114,7 +114,7 @@ static int __wrn_alloc_tx_desc(struct wrn_dev *wrn)
/* Actual transmission over a single endpoint */
static
void
__wrn_tx_desc
(
struct
wrn_ep
*
ep
,
int
desc
,
void
*
data
,
int
len
,
int
id
)
void
*
data
,
int
len
,
int
id
,
int
do_stamp
)
{
struct
wrn_dev
*
wrn
=
ep
->
wrn
;
int
offset
=
__wrn_desc_offset
(
wrn
,
WRN_DDIR_TX
,
desc
);
...
...
@@ -133,11 +133,12 @@ static void __wrn_tx_desc(struct wrn_ep *ep, int desc,
writel
(
1
<<
ep
->
ep_number
,
&
tx
->
tx3
);
/* TX register 2: ofset and length */
/* TX register 2: of
f
set and length */
writel
(
offset
|
(
len
<<
16
),
&
tx
->
tx2
);
/* TX register 1: id and masks */
writel
((
len
<
46
?
NIC_TX1_D1_PAD_E
:
0
)
|
NIC_TX1_D1_READY
|
(
id
<<
16
),
/* TX register 1: id and masks -- and tx_enable if needed */
writel
((
len
<
60
?
NIC_TX1_D1_PAD_E
:
0
)
|
NIC_TX1_D1_READY
|
(
do_stamp
?
NIC_TX1_D1_TS_E
:
0
)
|
(
id
<<
16
),
&
tx
->
tx1
);
}
...
...
@@ -146,11 +147,12 @@ static int wrn_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct
wrn_ep
*
ep
=
netdev_priv
(
dev
);
struct
wrn_dev
*
wrn
=
ep
->
wrn
;
//
union skb_shared_tx *shtx = skb_tx(skb);
union
skb_shared_tx
*
shtx
=
skb_tx
(
skb
);
unsigned
long
flags
;
int
desc
;
int
id
;
void
*
data
;
int
do_stamp
=
0
;
void
*
data
;
/* FIXME: move data and len to __wrn_tx_desc */
unsigned
len
;
if
(
unlikely
(
skb
->
len
>
WRN_MTU
))
{
...
...
@@ -162,7 +164,7 @@ static int wrn_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Allocate a descriptor and id (start from last allocated) */
spin_lock_irqsave
(
&
wrn
->
lock
,
flags
);
desc
=
__wrn_alloc_tx_desc
(
wrn
);
id
=
wrn
->
id
++
;
id
=
(
wrn
->
id
++
)
&
0xffff
;
spin_unlock_irqrestore
(
&
wrn
->
lock
,
flags
);
if
(
desc
<
0
)
/* error */
...
...
@@ -173,27 +175,24 @@ static int wrn_start_xmit(struct sk_buff *skb, struct net_device *dev)
//spin_lock_irqsave(&ep->lock, flags);
wrn
->
skb_desc
[
desc
]
=
skb
;
/* Save for tx irq and stamping */
//netif_stop_queue(dev); /* Queue stopped until tx is over (FIXME?) */
if
(
wrn
->
skb_desc
[
desc
].
skb
)
{
pr_err
(
"%s: descriptor overflow: tx timestamp pending
\n
"
,
__func__
);
}
wrn
->
skb_desc
[
desc
].
skb
=
skb
;
/* Save for tx irq and stamping */
wrn
->
skb_desc
[
desc
].
id
=
id
;
/* Save for tx irq and stamping */
if
(
test_bit
(
WRN_EP_STAMPING_TX
,
&
ep
->
ep_flags
))
{
#if 0 /* FIXME: the hw tx stamping */
struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
shtx->in_progress = 1;
*(u16 *) hwts = tx_oob = nic->tx_hwtstamp_oob;
//netif_stop_queue(dev); /* Queue stopped until tx is over (FIXME?) */
nic->tx_hwtstamp_oob ++;
if(nic->tx_hwtstamp_oob == 60000)
nic->tx_hwtstamp_oob = 1;
#endif
/* FIXME: check the WRN_EP_STAMPING_TX flag and its meaning */
if
(
shtx
->
hardware
)
{
/* hardware timestamping is enabled */
do_stamp
=
1
;
}
/* Mark the owner of this descriptor */
wrn
->
skb_desc
[
desc
]
=
skb
;
/* This both copies the data to the descriptr and fires tx */
printk
(
"%s: %i
\n
"
,
__func__
,
__LINE__
);
__wrn_tx_desc
(
ep
,
desc
,
data
,
len
,
id
);
__wrn_tx_desc
(
ep
,
desc
,
data
,
len
,
id
,
do_stamp
);
printk
(
"%s: %i
\n
"
,
__func__
,
__LINE__
);
/* We are done, this is trivial maiintainance*/
...
...
@@ -306,8 +305,6 @@ static void __wrn_rx_descriptor(struct wrn_dev *wrn, int desc)
dev
=
wrn
->
dev
[
epnum
];
ep
=
netdev_priv
(
dev
);
/* FIXME: rx timestamp */
/* Data and length */
off
=
NIC_RX1_D3_OFFSET_R
(
r3
);
len
=
NIC_RX1_D3_LEN_R
(
r3
);
...
...
@@ -375,6 +372,7 @@ static void wrn_tx_interrupt(struct wrn_dev *wrn)
{
struct
wrn_txd
*
tx
;
struct
sk_buff
*
skb
;
union
skb_shared_tx
*
shtx
;
u32
reg
;
int
i
;
...
...
@@ -386,12 +384,19 @@ static void wrn_tx_interrupt(struct wrn_dev *wrn)
if
(
reg
&
NIC_TX1_D1_READY
)
return
;
/* no more */
skb
=
wrn
->
skb_desc
[
i
];
/* FIXME: get the stamp from the fifo */
dev_kfree_skb_irq
(
skb
);
wrn
->
skb_desc
[
i
]
=
0
;
skb
=
wrn
->
skb_desc
[
i
].
skb
;
shtx
=
skb_tx
(
skb
);
if
(
shtx
->
hardware
)
{
/* hardware timestamping is enabled */
shtx
->
in_progress
=
1
;
printk
(
"%s: %i -- in progress
\n
"
,
__func__
,
__LINE__
);
wrn_tstamp_find_skb
(
wrn
,
i
);
/* It has been freed if found; otherwise keep it */
}
else
{
dev_kfree_skb_irq
(
skb
);
wrn
->
skb_desc
[
i
].
skb
=
0
;
}
wrn
->
next_tx_tail
=
__wrn_next_desc
(
i
);
}
}
...
...
nic/timestamp.c
View file @
accbd802
...
...
@@ -15,46 +15,101 @@
#include "wr-nic.h"
static
int
record_tstamp
(
struct
wrn_dev
*
wrn
,
u32
ts
,
u8
port_id
,
u16
frame_id
)
/* This looks for an skb in the already-received stamp list */
void
wrn_tstamp_find_skb
(
struct
wrn_dev
*
wrn
,
int
desc
)
{
struct
skb_shared_hwtstamps
*
hwts
;
struct
sk_buff
*
skb
=
wrn
->
skb_desc
[
desc
].
skb
;
int
id
=
wrn
->
skb_desc
[
desc
].
id
;
u32
counter_ppsg
;
/* PPS generator nanosecond counter */
u32
utc
;
int
i
;
/* FIXME: use list for faster access */
pr_debug
(
"%s: Got TS: %x pid %d fid %d
\n
"
,
__func__
,
ts
,
port_id
,
frame_id
);
for
(
i
=
0
;
i
<
WRN_TS_BUF_SIZE
;
i
++
)
if
(
!
wrn
->
ts_buf
[
i
].
valid
)
{
wrn
->
ts_buf
[
i
].
ts
=
ts
;
wrn
->
ts_buf
[
i
].
port_id
=
port_id
;
wrn
->
ts_buf
[
i
].
frame_id
=
frame_id
;
wrn
->
ts_buf
[
i
].
valid
=
1
;
return
0
;
}
/* no space in TS buffer? */
return
-
ENOMEM
;
for
(
i
=
0
;
i
<
WRN_TS_BUF_SIZE
;
i
++
)
if
(
wrn
->
ts_buf
[
i
].
valid
&&
wrn
->
ts_buf
[
i
].
frame_id
==
id
)
break
;
if
(
i
==
WRN_TS_BUF_SIZE
)
{
pr_debug
(
"%s: not found
\n
"
,
__func__
);
return
;
}
pr_debug
(
"%s: found
\n
"
,
__func__
);
/* so we found the skb, do the timestamping magic */
hwts
=
skb_hwtstamps
(
skb
);
wrn_ppsg_read_time
(
wrn
,
&
counter_ppsg
,
&
utc
);
if
(
counter_ppsg
<
wrn
->
ts_buf
[
i
].
ts
)
utc
--
;
hwts
->
hwtstamp
.
tv
.
sec
=
(
s32
)
utc
&
0x7fffffff
;
hwts
->
hwtstamp
.
tv
.
nsec
=
wrn
->
ts_buf
[
i
].
ts
*
8
;
/* scale to nsecs */
skb_tstamp_tx
(
skb
,
hwts
);
dev_kfree_skb_irq
(
skb
);
/* release both the descriptor and the tstamp entry */
wrn
->
skb_desc
[
desc
].
skb
=
0
;
wrn
->
ts_buf
[
i
].
valid
=
0
;
}
void
wrn_tstamp_init
(
struct
wrn_dev
*
wrn
)
/* This function records the timestamp in a list -- called from interrupt */
static
int
record_tstamp
(
struct
wrn_dev
*
wrn
,
u32
ts
,
u32
idreg
)
{
memset
(
wrn
->
ts_buf
,
0
,
sizeof
(
wrn
->
ts_buf
));
/* enable TXTSU irq */
writel
(
TXTSU_EIC_IER_NEMPTY
,
&
wrn
->
txtsu_regs
->
EIC_IER
);
int
port_id
=
TXTSU_TSF_R1_PID_R
(
idreg
);
int
frame_id
=
TXTSU_TSF_R1_FID_R
(
idreg
);
struct
skb_shared_hwtstamps
*
hwts
;
struct
sk_buff
*
skb
;
u32
utc
,
counter_ppsg
;
/* PPS generator nanosecond counter */
int
i
;
/* FIXME: use list for faster access */
pr_debug
(
"%s: Got TS: %x pid %d fid %d
\n
"
,
__func__
,
ts
,
port_id
,
frame_id
);
/* First of all look if the skb is already pending */
for
(
i
=
0
;
i
<
WRN_NR_DESC
;
i
++
)
if
(
wrn
->
skb_desc
[
i
].
skb
&&
wrn
->
skb_desc
[
i
].
id
==
frame_id
)
break
;
if
(
i
<
WRN_NR_DESC
)
{
pr_debug
(
"%s: found
\n
"
,
__func__
);
skb
=
wrn
->
skb_desc
[
i
].
skb
;
hwts
=
skb_hwtstamps
(
skb
);
wrn_ppsg_read_time
(
wrn
,
&
counter_ppsg
,
&
utc
);
if
(
counter_ppsg
<
wrn
->
ts_buf
[
i
].
ts
)
utc
--
;
hwts
->
hwtstamp
.
tv
.
sec
=
(
s32
)
utc
&
0x7fffffff
;
hwts
->
hwtstamp
.
tv
.
nsec
=
ts
*
8
;
/* scale to nanoseconds */
skb_tstamp_tx
(
skb
,
hwts
);
dev_kfree_skb_irq
(
skb
);
wrn
->
skb_desc
[
i
].
skb
=
0
;
}
/* Otherwise, save it to the list */
for
(
i
=
0
;
i
<
WRN_TS_BUF_SIZE
;
i
++
)
if
(
!
wrn
->
ts_buf
[
i
].
valid
)
break
;
if
(
i
==
WRN_TS_BUF_SIZE
)
{
pr_debug
(
"%s: ENOMEM
\n
"
,
__func__
);
return
-
ENOMEM
;
}
pr_debug
(
"%s: save to slot %i
\n
"
,
__func__
,
i
);
wrn
->
ts_buf
[
i
].
ts
=
ts
;
wrn
->
ts_buf
[
i
].
port_id
=
port_id
;
wrn
->
ts_buf
[
i
].
frame_id
=
frame_id
;
wrn
->
ts_buf
[
i
].
valid
=
1
;
return
0
;
}
irqreturn_t
wrn_tstamp_interrupt
(
int
irq
,
void
*
dev_id
)
{
struct
wrn_dev
*
wrn
=
dev_id
;
struct
TXTSU_WB
*
regs
=
wrn
->
txtsu_regs
;
/* FIXME: locking */
u32
r0
,
r1
;
printk
(
"%s: %i
\n
"
,
__func__
,
__LINE__
);
/* FIXME: locking */
r0
=
readl
(
&
regs
->
TSF_R0
);
r1
=
readl
(
&
regs
->
TSF_R1
);
if
(
record_tstamp
(
wrn
,
r0
,
TXTSU_TSF_R1_PID_R
(
r1
),
TXTSU_TSF_R1_FID_R
(
r1
))
<
0
)
{
if
(
record_tstamp
(
wrn
,
r0
,
r1
)
<
0
)
{
printk
(
"%s: ENOMEM in the TS buffer. Disabling TX stamping.
\n
"
,
__func__
);
writel
(
TXTSU_EIC_IER_NEMPTY
,
&
wrn
->
txtsu_regs
->
EIC_IDR
);
...
...
@@ -112,3 +167,11 @@ int wrn_tstamp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return
-
EFAULT
;
return
0
;
}
void
wrn_tstamp_init
(
struct
wrn_dev
*
wrn
)
{
memset
(
wrn
->
ts_buf
,
0
,
sizeof
(
wrn
->
ts_buf
));
/* enable TXTSU irq */
writel
(
TXTSU_EIC_IER_NEMPTY
,
&
wrn
->
txtsu_regs
->
EIC_IER
);
}
nic/wr-nic.h
View file @
accbd802
...
...
@@ -46,10 +46,10 @@
{NULL, wrn_interrupt, NULL, NULL, wrn_tstamp_interrupt}
#endif
/* Temporarily,
one handler
only */
#define WRN_IRQ_NUMBERS {WRN_IRQ_NIC}
#define WRN_IRQ_NAMES {"wr-nic"}
#define WRN_IRQ_HANDLERS {wrn_interrupt}
/* Temporarily,
two handlers
only */
#define WRN_IRQ_NUMBERS {WRN_IRQ_NIC
, WRN_IRQ_TSTAMP
}
#define WRN_IRQ_NAMES {"wr-nic"
, "wr-tstamp"
}
#define WRN_IRQ_HANDLERS {wrn_interrupt
, wrn_tstamp_interrupt
}
#define WRN_TS_BUF_SIZE 1024
/* array of timestamp structures */
...
...
@@ -63,6 +63,12 @@ struct wrn_tx_tstamp {
u32
ts
;
};
/* We must remember both skb and id for each pending descriptor */
struct
wrn_desc_pending
{
struct
sk_buff
*
skb
;
u32
id
;
/* only 16 bits, actually */
};
/*
* This is the main data structure for our NIC device. As for locking,
* the rule is that _either_ the wrn _or_ the endpoint is locked. Not both.
...
...
@@ -83,7 +89,7 @@ struct wrn_dev {
int
next_rx
;
/* For TX descriptors, we must keep track of the ownwer */
struct
sk_buff
*
skb_desc
[
WRN_NR_TXDESC
];
struct
wrn_desc_pending
skb_desc
[
WRN_NR_TXDESC
];
int
id
;
struct
net_device
*
dev
[
WRN_NR_ENDPOINTS
];
...
...
@@ -213,8 +219,10 @@ extern int wrn_endpoint_probe(struct net_device *netdev);
extern
void
wrn_endpoint_remove
(
struct
net_device
*
netdev
);
/* Following functions from timestamp.c */
extern
void
wrn_tstamp_find_skb
(
struct
wrn_dev
*
wrn
,
int
i
);
extern
int
wrn_tstamp_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
extern
irqreturn_t
wrn_tstamp_interrupt
(
int
irq
,
void
*
dev_id
);
extern
void
wrn_tstamp_init
(
struct
wrn_dev
*
wrn
);
/* Following functions from dmtd.c */
extern
int
wrn_phase_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
...
...
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