summaryrefslogtreecommitdiffstats
path: root/drivers/net/fddi
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2018-10-10 00:57:49 +0200
committerDavid S. Miller <davem@davemloft.net>2018-10-16 06:46:06 +0200
commit9f9a742db40f95f4dc20fc7293de4ea6ddb24e47 (patch)
tree5cbd5bcf3514e362f9f42275961b4880deb92fac /drivers/net/fddi
parentFDDI: defza: Add support for DEC FDDIcontroller 700 TURBOchannel adapter (diff)
downloadlinux-9f9a742db40f95f4dc20fc7293de4ea6ddb24e47.tar.xz
linux-9f9a742db40f95f4dc20fc7293de4ea6ddb24e47.zip
FDDI: defza: Support capturing outgoing SMT traffic
DEC FDDIcontroller 700 (DEFZA) uses a Tx/Rx queue pair to communicate SMT frames with adapter's firmware. Any SMT frame received from the RMC via the Rx queue is queued back by the driver to the SMT Rx queue for the firmware to process. Similarly the firmware uses the SMT Tx queue to supply the driver with SMT frames which are queued back to the Tx queue for the RMC to send to the ring. When a network tap is attached to an FDDI interface handled by `defza' any incoming SMT frames captured are queued to our usual processing of network data received, which in turn delivers them to any listening taps. However the outgoing SMT frames produced by the firmware bypass our network protocol stack and are therefore not delivered to taps. This in turn means that taps are missing a part of network traffic sent by the adapter, which may make it more difficult to track down network problems or do general traffic analysis. Call `dev_queue_xmit_nit' then in the SMT Tx path, having checked that a network tap is attached, with a newly-created `dev_nit_active' helper wrapping the usual condition used in the transmit path. Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/fddi')
-rw-r--r--drivers/net/fddi/defza.c33
1 files changed, 31 insertions, 2 deletions
diff --git a/drivers/net/fddi/defza.c b/drivers/net/fddi/defza.c
index 7d01b70f7ed8..3b7f10a5f06a 100644
--- a/drivers/net/fddi/defza.c
+++ b/drivers/net/fddi/defza.c
@@ -797,11 +797,40 @@ static void fza_tx_smt(struct net_device *dev)
smt_tx_ptr = fp->mmio + readl_u(&fp->ring_smt_tx[i].buffer);
len = readl_u(&fp->ring_smt_tx[i].rmc) & FZA_RING_PBC_MASK;
- /* Queue the frame to the RMC transmit ring. */
- if (!netif_queue_stopped(dev))
+ if (!netif_queue_stopped(dev)) {
+ if (dev_nit_active(dev)) {
+ struct sk_buff *skb;
+
+ /* Length must be a multiple of 4 as only word
+ * reads are permitted!
+ */
+ skb = fza_alloc_skb_irq(dev, (len + 3) & ~3);
+ if (!skb)
+ goto err_no_skb; /* Drop. */
+
+ skb_data_ptr = (struct fza_buffer_tx *)
+ skb->data;
+
+ fza_reads(smt_tx_ptr, skb_data_ptr,
+ (len + 3) & ~3);
+ skb->dev = dev;
+ skb_reserve(skb, 3); /* Skip over PRH. */
+ skb_put(skb, len - 3);
+ skb_reset_network_header(skb);
+
+ dev_queue_xmit_nit(skb, dev);
+
+ dev_kfree_skb_irq(skb);
+
+err_no_skb:
+ ;
+ }
+
+ /* Queue the frame to the RMC transmit ring. */
fza_do_xmit((union fza_buffer_txp)
{ .mmio_ptr = smt_tx_ptr },
len, dev, 1);
+ }
writel_o(FZA_RING_OWN_FZA, &fp->ring_smt_tx[i].own);
fp->ring_smt_tx_index =