Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
W
White Rabbit Network Interface Card
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
2
Issues
2
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
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 Network Interface Card
Commits
e09e5b30
Commit
e09e5b30
authored
Sep 04, 2019
by
Miguel Jimenez Lopez
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Changes for IRQ registering using a special IORESOURCE_BUS resource from parent driver.
parent
14c688f0
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
92 additions
and
75 deletions
+92
-75
device.c
sw/kernel/device.c
+83
-30
endpoint.c
sw/kernel/endpoint.c
+0
-6
module.c
sw/kernel/module.c
+4
-1
nic-core.c
sw/kernel/nic-core.c
+1
-17
nic-hardware.h
sw/kernel/nic-hardware.h
+0
-6
timestamp.c
sw/kernel/timestamp.c
+1
-1
wr-nic.h
sw/kernel/wr-nic.h
+3
-14
No files found.
sw/kernel/device.c
View file @
e09e5b30
/*
* Device initialization and cleanup for White-Rabbit switch network interface
*
* Copyright (C) 2019 Seven Solutions (sevensols.com)
* Author: Miguel Jimenez Lopez <miguel.jimenez@sevensols.com>
*
* Copyright (C) 2010 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
...
...
@@ -30,15 +33,30 @@
* a module parameter or somehow configurable. For the time being we keep
* it hard-coded here.
*/
#if WR_IS_SWITCH
static
const
char
*
irqdomain_name
=
"htvic-wr-swi.0"
;
#else
static
const
char
*
irqdomain_name
=
"htvic-spec.0"
;
#endif
#define HTVIC_IRQDOMAIN_NAME "htvic-irq"
static
struct
irq_domain
*
irq_find_irqdomain
(
const
char
*
name
)
{
struct
irq_fwspec
fwspec
;
struct
irq_domain
*
d
=
NULL
;
memset
(
&
fwspec
,
0
,
sizeof
(
fwspec
));
fwspec
.
fwnode
=
(
struct
fwnode_handle
*
)
name
;
fwspec
.
param_count
=
1
;
d
=
irq_find_matching_fwspec
(
&
fwspec
,
DOMAIN_BUS_ANY
);
return
d
;
}
static
inline
struct
wrn_dev
*
wrn_from_pdev
(
struct
platform_device
*
pdev
)
{
#if WR_IS_SWITCH
return
pdev
->
dev
.
platform_data
;
#else
return
&
wrn_dev
;
#endif
}
/* The remove function is used by probe, so it's not __devexit */
...
...
@@ -47,13 +65,24 @@ static int wrn_remove(struct platform_device *pdev)
struct
wrn_dev
*
wrn
=
wrn_from_pdev
(
pdev
);
int
i
,
irq
;
struct
irq_domain
*
irqdomain
;
irqdomain
=
irq_find_host
((
struct
device_node
*
)
irqdomain_name
);
char
*
irqdomain_name
;
struct
resource
*
r
;
r
=
platform_get_resource
(
pdev
,
IORESOURCE_BUS
,
0
);
irqdomain_name
=
kasprintf
(
GFP_KERNEL
,
"%s-%d:%d"
,
HTVIC_IRQDOMAIN_NAME
,
(
unsigned
char
)
((
!
r
)
?
0
:
r
->
start
),
(
unsigned
int
)
((
!
r
)
?
0
:
r
->
end
));
irqdomain
=
irq_find_irqdomain
(
irqdomain_name
);
if
(
!
irqdomain
)
{
dev_err
(
&
pdev
->
dev
,
"The IRQ domain %s does not exist
\n
"
,
irqdomain_name
);
return
-
EINVAL
;
}
kfree
(
irqdomain_name
);
if
(
WR_IS_SWITCH
)
{
spin_lock
(
&
wrn
->
lock
);
...
...
@@ -79,15 +108,28 @@ static int wrn_remove(struct platform_device *pdev)
iounmap
(
wrn
->
bases
[
i
]);
}
/* Unregister all interrupts that were registered */
for
(
i
=
0
;
wrn
->
irq_registered
;
i
++
)
{
static
int
irqs
[]
=
WRN_IRQ_NUMBERS
;
if
(
wrn
->
irq_registered
&
(
1
<<
i
))
{
irq
=
irq_find_mapping
(
irqdomain
,
irqs
[
i
]);
if
(
WR_IS_SWITCH
)
{
/* Unregister all interrupts that were registered */
for
(
i
=
0
;
wrn
->
irq_registered
;
i
++
)
{
static
int
irqs
[]
=
WRN_IRQ_NUMBERS
;
if
(
wrn
->
irq_registered
&
(
1
<<
i
))
{
irq
=
irq_find_mapping
(
irqdomain
,
irqs
[
i
]);
free_irq
(
irq
,
wrn
);
}
wrn
->
irq_registered
&=
~
(
1
<<
i
);
}
}
else
{
struct
resource
*
res
;
for
(
i
=
0
;
i
<
pdev
->
num_resources
;
i
++
)
{
res
=
platform_get_resource
(
pdev
,
IORESOURCE_IRQ
,
i
);
if
(
!
res
)
continue
;
irq
=
irq_find_mapping
(
irqdomain
,
res
->
start
);
free_irq
(
irq
,
wrn
);
wrn
->
irq_registered
&=
~
(
1
<<
i
);
}
wrn
->
irq_registered
&=
~
(
1
<<
i
);
}
return
0
;
}
...
...
@@ -107,6 +149,7 @@ static int __wrn_map_resources(struct platform_device *pdev)
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
i
);
if
(
!
res
||
!
res
->
start
)
continue
;
ptr
=
ioremap
(
res
->
start
,
res
->
end
+
1
-
res
->
start
);
if
(
!
ptr
)
{
dev_err
(
&
pdev
->
dev
,
"Remap for res %i %pr failed
\n
"
,
...
...
@@ -138,9 +181,9 @@ static int __wrn_map_irq(struct platform_device *pdev, struct irq_domain *irqdom
/* Register the interrupt handlers (not shared) */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
irq_names
);
i
++
)
{
irq
=
irq_find_mapping
(
irqdomain
,
irqs
[
i
]);
err
=
request_irq
(
irq
,
irq_handlers
[
i
],
err
=
request_
any_context_
irq
(
irq
,
irq_handlers
[
i
],
IRQF_TRIGGER_LOW
,
irq_names
[
i
],
wrn
);
if
(
err
)
if
(
err
<
0
)
break
;
wrn
->
irq_registered
|=
1
<<
i
;
}
...
...
@@ -151,15 +194,18 @@ static int __wrn_map_irq(struct platform_device *pdev, struct irq_domain *irqdom
if
(
!
res
)
continue
;
irq
=
irq_find_mapping
(
irqdomain
,
res
->
start
);
err
=
request_irq
(
irq
,
irq_handlers
[
i
],
IRQF_TRIGGER_LOW
,
res
->
name
,
wrn
);
if
(
err
)
err
=
request_any_context_irq
(
irq
,
irq_handlers
[
i
],
IRQF_TRIGGER_HIGH
,
res
->
name
,
wrn
);
if
(
err
<
0
)
{
printk
(
"%s: request_irq error %d
\n
"
,
__func__
,
err
);
break
;
}
wrn
->
irq_registered
|=
1
<<
i
;
}
}
return
err
;
return
(
err
<
0
)
?
err
:
0
;
}
static
int
wrn_probe
(
struct
platform_device
*
pdev
)
...
...
@@ -169,13 +215,24 @@ static int wrn_probe(struct platform_device *pdev)
struct
wrn_dev
*
wrn
=
wrn_from_pdev
(
pdev
);
int
i
,
err
=
0
;
struct
irq_domain
*
irqdomain
;
char
*
irqdomain_name
;
struct
resource
*
r
;
r
=
platform_get_resource
(
pdev
,
IORESOURCE_BUS
,
0
);
irqdomain_name
=
kasprintf
(
GFP_KERNEL
,
"%s-%d:%d"
,
HTVIC_IRQDOMAIN_NAME
,
(
unsigned
char
)
((
!
r
)
?
0
:
r
->
start
),
(
unsigned
int
)
((
!
r
)
?
0
:
r
->
end
));
irqdomain
=
irq_find_
host
((
struct
device_node
*
)
irqdomain_name
);
irqdomain
=
irq_find_
irqdomain
(
irqdomain_name
);
if
(
!
irqdomain
)
{
dev_err
(
&
pdev
->
dev
,
"The IRQ domain %s does not exist
\n
"
,
irqdomain_name
);
return
-
EINVAL
;
}
kfree
(
irqdomain_name
);
/* No need to lock_irq: we only protect count and continue unlocked */
if
(
WR_IS_SWITCH
)
{
...
...
@@ -191,6 +248,7 @@ static int wrn_probe(struct platform_device *pdev)
/* Map our resource list and instantiate the shortcut pointers */
if
(
(
err
=
__wrn_map_resources
(
pdev
))
)
goto
out
;
wrn
->
regs
=
wrn
->
bases
[
WRN_FB_NIC
];
wrn
->
txtsu_regs
=
wrn
->
bases
[
WRN_FB_TS
];
wrn
->
ppsg_regs
=
wrn
->
bases
[
WRN_FB_PPSG
];
...
...
@@ -198,10 +256,7 @@ static int wrn_probe(struct platform_device *pdev)
wrn
->
rxd
=
((
void
*
)
wrn
->
regs
)
+
0x100
;
/* was: RX1_D1 */
wrn
->
databuf
=
(
void
*
)
wrn
->
regs
+
NIC_MEM_BASE
;
tasklet_init
(
&
wrn
->
rx_tlet
,
wrn_rx_interrupt
,
(
unsigned
long
)
wrn
);
if
(
0
)
printk
(
"regs %p, txd %p, rxd %p, buffer %p
\n
"
,
wrn
->
regs
,
wrn
->
txd
,
wrn
->
rxd
,
wrn
->
databuf
);
;
/* Map our interrupts */
if
(
(
err
=
__wrn_map_irq
(
pdev
,
irqdomain
))
)
goto
out
;
...
...
@@ -216,15 +271,12 @@ static int wrn_probe(struct platform_device *pdev)
err
=
-
ENOMEM
;
goto
out
;
}
/* The ep structure is filled before calling ep_probe */
ep
=
netdev_priv
(
netdev
);
ep
->
wrn
=
wrn
;
ep
->
ep_regs
=
wrn
->
bases
[
WRN_FB_EP
]
+
i
*
FPGA_SIZE_EACH_EP
;
ep
->
ep_number
=
i
;
#if 0 /* FIXME: UPlink or not? */
if (i < WRN_NR_UPLINK)
set_bit(WRN_EP_IS_UPLINK, &ep->ep_flags);
#endif
/* The netdevice thing is registered from the endpoint */
err
=
wrn_endpoint_probe
(
netdev
);
...
...
@@ -232,6 +284,7 @@ static int wrn_probe(struct platform_device *pdev)
break
;
if
(
err
)
goto
out
;
/* This endpoint went in properly */
wrn
->
dev
[
i
]
=
netdev
;
err
=
wrn_mezzanine_init
(
netdev
);
...
...
@@ -247,7 +300,7 @@ static int wrn_probe(struct platform_device *pdev)
tx
=
wrn
->
txd
+
i
;
writel
(
0
,
&
tx
->
tx1
);
}
/* Now, prepare RX descriptors */
for
(
i
=
0
;
i
<
WRN_NR_RXDESC
;
i
++
)
{
struct
wrn_rxd
*
rx
;
...
...
@@ -258,7 +311,6 @@ static int wrn_probe(struct platform_device *pdev)
writel
(
(
2000
<<
16
)
|
offset
,
&
rx
->
rx3
);
writel
(
NIC_RX1_D1_EMPTY
,
&
rx
->
rx1
);
}
/*
* make sure all head/tail are 0 -- not needed here, but if we
* disable and then re-enable, this _is_ needed
...
...
@@ -277,6 +329,7 @@ out:
}
else
{
dev_info
(
&
pdev
->
dev
,
"White Rabbit NIC driver
\n
"
);
}
return
err
;
}
...
...
sw/kernel/endpoint.c
View file @
e09e5b30
...
...
@@ -110,15 +110,11 @@ static void wrn_update_link_status(struct net_device *dev)
bmsr
=
wrn_phy_read
(
dev
,
0
,
MII_BMSR
);
bmcr
=
wrn_phy_read
(
dev
,
0
,
MII_BMCR
);
//netdev_dbg(dev, "%s: read %x %x", __func__, bmsr, bmcr);
// printk("%s: read %x %x %x\n", __func__, bmsr, bmcr);
/* Link wnt down? */
if
(
!
mii_link_ok
(
&
ep
->
mii
))
{
if
(
netif_carrier_ok
(
dev
))
{
netif_carrier_off
(
dev
);
clear_bit
(
WRN_EP_UP
,
&
ep
->
ep_flags
);
printk
(
KERN_INFO
"%s: Link down.
\n
"
,
dev
->
name
);
return
;
}
return
;
...
...
@@ -147,8 +143,6 @@ static void wrn_update_link_status(struct net_device *dev)
|
EP_FCR_TX_QUANTA_W
(
200
));
}
printk
(
KERN_INFO
"%s: Link up, lpa 0x%04x.
\n
"
,
dev
->
name
,
lpa
);
}
else
{
/* No autonegotiation. It's up immediately */
printk
(
KERN_INFO
"%s: Link up.
\n
"
,
dev
->
name
);
...
...
sw/kernel/module.c
View file @
e09e5b30
...
...
@@ -19,9 +19,12 @@
#include "wr-nic.h"
#if WR_IS_SWITCH
/* Our platform data is actually the device itself, and we have 1 only */
static
struct
wrn_dev
wrn_dev
;
#else
struct
wrn_dev
wrn_dev
;
#endif
#if WR_IS_SWITCH
/* The WRN_RES_ names are defined in the header file. Each block 64kB */
...
...
sw/kernel/nic-core.c
View file @
e09e5b30
...
...
@@ -66,7 +66,6 @@ static int wrn_open(struct net_device *dev)
u32
val
;
/* This is "open" just for an endpoint. The nic hw is already on */
//netdev_dbg(dev, "%s\n", __func__);
if
(
!
is_valid_ether_addr
(
dev
->
dev_addr
))
return
-
EADDRNOTAVAIL
;
...
...
@@ -124,10 +123,7 @@ static int wrn_set_mac_address(struct net_device *dev, void* vaddr)
struct
sockaddr
*
addr
=
vaddr
;
u32
val
;
//netdev_dbg(dev, "%s\n", __func__);
if
(
!
is_valid_ether_addr
(
addr
->
sa_data
))
{
//netdev_dbg(dev, "%s: invalid\n", __func__);
return
-
EADDRNOTAVAIL
;
}
...
...
@@ -181,8 +177,6 @@ static void __wrn_tx_desc(struct wrn_ep *ep, int desc,
__wrn_copy_out
(
ptr
,
data
,
len
);
/* TX register 3: mask of endpoints (FIXME: broadcast) */
//printk("EP Num: %d\n", ep->ep_number);
writel
(
1
<<
ep
->
ep_number
,
&
tx
->
tx3
);
/* TX register 2: offset and length */
...
...
@@ -227,8 +221,6 @@ static int wrn_start_xmit(struct sk_buff *skb, struct net_device *dev)
data
=
skb
->
data
;
len
=
skb
->
len
;
//spin_lock_irqsave(&ep->lock, flags);
if
(
wrn
->
skb_desc
[
desc
].
skb
)
{
pr_warn
(
"%s: discarding tx frame that got no timestamp
\n
"
,
__func__
);
...
...
@@ -237,8 +229,6 @@ static int wrn_start_xmit(struct sk_buff *skb, struct net_device *dev)
wrn
->
skb_desc
[
desc
].
skb
=
skb
;
/* Save for tx irq and stamping */
wrn
->
skb_desc
[
desc
].
frame_id
=
id
;
/* Save for tx irq and stamping */
//netif_stop_queue(dev); /* Queue stopped until tx is over (FIXME?) */
/* FIXME: check the WRN_EP_STAMPING_TX flag and its meaning */
if
(
info
->
tx_flags
&
SKBTX_HW_TSTAMP
)
{
/* hardware timestamping is enabled */
...
...
@@ -253,7 +243,6 @@ static int wrn_start_xmit(struct sk_buff *skb, struct net_device *dev)
ep
->
stats
.
tx_bytes
+=
len
;
trans_update
(
dev
);
//spin_unlock_irqrestore(&ep->lock, flags);
return
0
;
}
...
...
@@ -356,12 +345,6 @@ static const struct net_device_ops wrn_netdev_ops = {
.
ndo_get_stats
=
wrn_get_stats
,
.
ndo_set_mac_address
=
wrn_set_mac_address
,
.
ndo_do_ioctl
=
wrn_ioctl
,
#if 0
/* Missing ops, possibly to add later */
.ndo_set_multicast_list = wrn_set_multicast_list,
.ndo_change_mtu = wrn_change_mtu,
/* There are several more, but not really useful for us */
#endif
};
...
...
@@ -575,5 +558,6 @@ irqreturn_t wrn_interrupt(int irq, void *dev_id)
writel
(
NIC_EIC_ISR_RCOMP
,
(
void
*
)
regs
+
0x2c
);
tasklet_schedule
(
&
wrn
->
rx_tlet
);
}
return
IRQ_HANDLED
;
}
sw/kernel/nic-hardware.h
View file @
e09e5b30
...
...
@@ -23,9 +23,6 @@
#define WRN_IRQ_BASE 0
#define WRN_IRQ_NIC (WRN_IRQ_BASE + 0)
#define WRN_IRQ_TSTAMP (WRN_IRQ_BASE + 1)
//#define WRN_IRQ_PPSG (WRN_IRQ_BASE + )
//#define WRN_IRQ_RTU (WRN_IRQ_BASE + )
//#define WRN_IRQ_RTUT (WRN_IRQ_BASE + )
/*
* V3 Memory map, temporarily (Jan 2012)
...
...
@@ -68,9 +65,6 @@
#define WRN_IRQ_BASE 0
/* FIXME: relative to pci dev */
#define WRN_IRQ_NIC (WRN_IRQ_BASE + 0)
#define WRN_IRQ_TSTAMP
/* (WRN_IRQ_BASE + 1) -- not used here */
//#define WRN_IRQ_PPSG (WRN_IRQ_BASE + )
//#define WRN_IRQ_RTU (WRN_IRQ_BASE + )
//#define WRN_IRQ_RTUT (WRN_IRQ_BASE + )
/*
* spec-wr-nic memory map (from SDB dump):
...
...
sw/kernel/timestamp.c
View file @
e09e5b30
...
...
@@ -98,7 +98,6 @@ irqreturn_t wrn_tstamp_interrupt(int irq, void *dev_id)
struct
TXTSU_WB
*
regs
=
wrn
->
txtsu_regs
;
u32
r0
,
r1
,
r2
;
/* printk("%s: %i\n", __func__, __LINE__); */
/* FIXME: locking */
r0
=
readl
(
&
regs
->
TSF_R0
);
r1
=
readl
(
&
regs
->
TSF_R1
);
...
...
@@ -106,6 +105,7 @@ irqreturn_t wrn_tstamp_interrupt(int irq, void *dev_id)
record_tstamp
(
wrn
,
r0
,
r1
,
r2
);
writel
(
TXTSU_EIC_IER_NEMPTY
,
&
wrn
->
txtsu_regs
->
EIC_ISR
);
/* ack irq */
return
IRQ_HANDLED
;
}
...
...
sw/kernel/wr-nic.h
View file @
e09e5b30
...
...
@@ -106,14 +106,6 @@ struct wrn_dev {
struct
net_device
*
dev
[
WRN_NR_ENDPOINTS
];
/* FIXME: all dev fields must be verified */
//unsigned int rx_head, rx_avail, rx_base, rx_size;
//unsigned int tx_head, tx_avail, tx_base, tx_size;
//u32 cur_rx_desc;
int
use_count
;
/* only used at probe time */
int
irq_registered
;
};
...
...
@@ -135,12 +127,6 @@ struct wrn_ep {
int
pkt_count
;
/* used for tx stamping ID */
struct
net_device_stats
stats
;
//struct sk_buff *current_skb;
//bool synced;
//bool syncing_counters;
//u32 cur_rx_desc;
};
#define WRN_LINK_POLL_INTERVAL (HZ/5)
...
...
@@ -216,6 +202,9 @@ struct wrn_phase_req {
#define WRN_MDIO_WR_SPEC_RX_CAL_STAT 0x02
/* RX calib status */
#define WRN_MDIO_WR_SPEC_CAL_CRST 0x04
/* Reset calibration counter */
#if WR_IS_NODE
extern
struct
wrn_dev
wrn_dev
;
#endif
/* Following functions are in nic-core.c */
extern
irqreturn_t
wrn_interrupt
(
int
irq
,
void
*
dev_id
);
...
...
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