xilinx_emacps: Fix locking issues

The existing driver has locking issues. This patch fixes them.
The locking issues/warnings are mainly because some of the routines
are trying to acquire tx and rx locks both. Acquiring of both locks
was implemented because net_ctrl register was getting accessed on
both tx and rx paths and also in the timer handler meant to provide
a workaround for the Rx path sillicon issue. To maintain a consistent
net_ctrl register, some of the routines had to acquire both locks.
To fix this, this patch provides one more lock that is used only for
the net_ctrl register. This provides a much cleaner locking mechanism.
Also, after much analysis it was figured out that, some of the APIs
(e.g. xemacps_close and ethtool APIs) do not need any locks.
Some of the locking related warnings were because of these APIs
acquiring both the locks. This patch addresses them.

Signed-off-by: Anirudha Sarangi <anirudh@xilinx.com>
Tested-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
xilinx_emacps: Fix handling of skb fragments (1/3)

xemacps_clean_rings() needs to know the fragment length for unmapping
a Tx skb fragment -- skb->len is only correct for the first fragment.

For this, we add a field 'len' to 'struct ring_info'. We employ this
field for Rx packets as well, if only to avoid using the constant
XEMACPS_RX_BUF_SIZE everywhere.

Note: We also fix a minor issue with the tx_bytes statistics counter in
xemacps_tx_poll(); it was found when dropping the 'leninbd' variable
(which is no longer needed).

Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com>
Tested-by: Anirudha Sarangi <anirudh@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
xilinx_emacps: Fix handling of skb fragments (2/3)

In xemacps_start_xmit(), we cannot set tx_skb[].skb = NULL for a
fragment because xemacps_clean_rings() uses skb as a flag to call
dma_unmap_single().

Instead, we simply increment the skb's user count by skb_get() so that
dev_kfree_skb() can [and must] be called multiple times.

Note that the last dev_kfree_skb() in xemacps_clean_rings() will be
called after the last dma_unmap_single(), even if there is a wrap in
the middle of the packet; i.e., the socket buffer will be valid until
all DMA regions are unmapped.

Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com>
Tested-by: Anirudha Sarangi <anirudh@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
xilinx_emacps: Fix handling of skb fragments (3/3)

When a Tx packet is fragmented, the controller sets USED=1 only in the
first buffer. This means that xemacps_tx_poll() cannot "preserve" the
USED bit (which may be 0), but must set USED=1 explicitly once the
packet has been transmitted.

Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com>
Tested-by: Anirudha Sarangi <anirudh@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
xilinx_emacps: Read statistics registers only once

Statistics registers are clear-on-read, so xemacps_update_stats() must
take care to read each of them only once -- extra reads will usually
return 0, leading to inconsistencies.

Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com>
Tested-by: Anirudha Sarangi <anirudh@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
xilinx_emacps: Fix rx_errors and tx_errors

Some minor improvements in xemacps_update_stats():
o Count RXRESERR in rx_missed_errors.
o Count RXOR only in rx_fifo_errors, not twice in rx_fifo_errors and
  rx_over_errors (the latter are bundled with frame errors).
o Do not count SNGLCOLL and MULTICOLL in tx_errors (only in collisions)
  because the packets were successfully transmitted after all.

Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com>
Tested-by: Anirudha Sarangi <anirudh@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
xilinx_emacps: Log severe errors, fix tx_packets

Certain severe error conditions (which should never occur) should be
logged, in particular since the driver does not take actions to
recover; see 16.3.10 in the TRM. Some kind of dev_err() already used to
exist in previous driver versions, but got lost somehow:
o In xemacps_rx_poll(), log rx_status.HRESPNOK.
o In xemacps_tx_poll(), log tx_status.HRESPNOK and .BUFEXH.

Note: Some rx_status and tx_status error conditions are not covered by
statistics registers. There also used to be some code to increment the
net_device_stats counters, but I have refrained from re-adding it:
o rx_status.HRESPNOK: rx_errors, rx_fifo_errors
o rx_status.RXOVR:    rx_errors, rx_fifo_errors
o tx_status.HRESPNOK: tx_errors, tx_fifo_errors
o tx_status.BUFEXH:   tx_errors, tx_fifo_errors

In xemacps_tx_poll(), increment tx_packets and tx_bytes even if the
transmission failed. This is expected by SNMP (see ifOutUcastPkts in
RFC 2863: "The total number of packets that higher-level protocols
requested be transmitted, ..., including those that were discarded or
not sent."), and other Ethernet drivers also seem to handle it this way.

Note: In order to decide if an error occurred, we would need to check
the ERR bits of all buffers of a (multi-fragment) packet, not just the
last buffer; it is actually easier to drop this altogether, though.

Signed-off-by: Thomas Betker <thomas.betker@rohde-schwarz.com>
Tested-by: Anirudha Sarangi <anirudh@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
net: xemacps: Merge if-blocks

Merging two if-blocks which checked identical conditionals.

Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Tested-by: Anirudha Sarangi <anirudh@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
net: xemacps: Remove warning on round_rate failure

Assume that we deal with an input clock which is adjusted by different
means than the CCF when clk_round_rate() fails and remove the warning
message.
This allows warning free usage of an EMIO clock source w/o a CCF clock
driver on cost of that we don't detect an actual failing call to
clk_round_rate() which I think is rather unlikely to happen.

Signed-off-by: Soren Brinkmann <soren.brinkmann@xilinx.com>
Tested-by: Anirudha Sarangi <anirudh@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>