|
@@ -70,7 +70,8 @@
|
|
|
#define XEL_TSR_XMIT_IE_MASK 0x00000008 /* Tx interrupt enable bit */
|
|
|
#define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000 /* Buffer is active, SW bit
|
|
|
* only. This is not documented
|
|
|
- * in the HW spec */
|
|
|
+ * in the HW spec
|
|
|
+ */
|
|
|
|
|
|
/* Define for programming the MAC address into the EmacLite */
|
|
|
#define XEL_TSR_PROG_MAC_ADDR (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK)
|
|
@@ -94,11 +95,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
-#define TX_TIMEOUT (60*HZ) /* Tx timeout is 60 seconds. */
|
|
|
+#define TX_TIMEOUT (60 * HZ) /* Tx timeout is 60 seconds. */
|
|
|
#define ALIGNMENT 4
|
|
|
|
|
|
/* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
|
|
|
-#define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT)
|
|
|
+#define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32)adr)) % ALIGNMENT)
|
|
|
|
|
|
#ifdef __BIG_ENDIAN
|
|
|
#define xemaclite_readl ioread32be
|
|
@@ -238,8 +239,8 @@ static void xemaclite_aligned_write(void *src_ptr, u32 *dest_ptr,
|
|
|
|
|
|
/* Set up to output the remaining data */
|
|
|
align_buffer = 0;
|
|
|
- to_u8_ptr = (u8 *) &align_buffer;
|
|
|
- from_u8_ptr = (u8 *) from_u16_ptr;
|
|
|
+ to_u8_ptr = (u8 *)&align_buffer;
|
|
|
+ from_u8_ptr = (u8 *)from_u16_ptr;
|
|
|
|
|
|
/* Output the remaining data */
|
|
|
for (; length > 0; length--)
|
|
@@ -272,7 +273,7 @@ static void xemaclite_aligned_read(u32 *src_ptr, u8 *dest_ptr,
|
|
|
u32 align_buffer;
|
|
|
|
|
|
from_u32_ptr = src_ptr;
|
|
|
- to_u16_ptr = (u16 *) dest_ptr;
|
|
|
+ to_u16_ptr = (u16 *)dest_ptr;
|
|
|
|
|
|
for (; length > 3; length -= 4) {
|
|
|
/* Copy each word into the temporary buffer */
|
|
@@ -288,9 +289,9 @@ static void xemaclite_aligned_read(u32 *src_ptr, u8 *dest_ptr,
|
|
|
u8 *to_u8_ptr, *from_u8_ptr;
|
|
|
|
|
|
/* Set up to read the remaining data */
|
|
|
- to_u8_ptr = (u8 *) to_u16_ptr;
|
|
|
+ to_u8_ptr = (u8 *)to_u16_ptr;
|
|
|
align_buffer = *from_u32_ptr++;
|
|
|
- from_u8_ptr = (u8 *) &align_buffer;
|
|
|
+ from_u8_ptr = (u8 *)&align_buffer;
|
|
|
|
|
|
/* Read the remaining data */
|
|
|
for (; length > 0; length--)
|
|
@@ -336,7 +337,8 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
|
|
|
drvdata->next_tx_buf_to_use ^= XEL_BUFFER_OFFSET;
|
|
|
} else if (drvdata->tx_ping_pong != 0) {
|
|
|
/* If the expected buffer is full, try the other buffer,
|
|
|
- * if it is configured in HW */
|
|
|
+ * if it is configured in HW
|
|
|
+ */
|
|
|
|
|
|
addr = (void __iomem __force *)((u32 __force)addr ^
|
|
|
XEL_BUFFER_OFFSET);
|
|
@@ -349,7 +351,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
|
|
|
return -1; /* Buffer was full, return failure */
|
|
|
|
|
|
/* Write the frame to the buffer */
|
|
|
- xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
|
|
|
+ xemaclite_aligned_write(data, (u32 __force *)addr, byte_count);
|
|
|
|
|
|
xemaclite_writel((byte_count & XEL_TPLR_LENGTH_MASK),
|
|
|
addr + XEL_TPLR_OFFSET);
|
|
@@ -357,7 +359,8 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
|
|
|
/* Update the Tx Status Register to indicate that there is a
|
|
|
* frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
|
|
|
* is used by the interrupt handler to check whether a frame
|
|
|
- * has been transmitted */
|
|
|
+ * has been transmitted
|
|
|
+ */
|
|
|
reg_data = xemaclite_readl(addr + XEL_TSR_OFFSET);
|
|
|
reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
|
|
|
xemaclite_writel(reg_data, addr + XEL_TSR_OFFSET);
|
|
@@ -369,6 +372,7 @@ static int xemaclite_send_data(struct net_local *drvdata, u8 *data,
|
|
|
* xemaclite_recv_data - Receive a frame
|
|
|
* @drvdata: Pointer to the Emaclite device private data
|
|
|
* @data: Address where the data is to be received
|
|
|
+ * @maxlen: Maximum supported ethernet packet length
|
|
|
*
|
|
|
* This function is intended to be called from the interrupt context or
|
|
|
* with a wrapper which waits for the receive frame to be available.
|
|
@@ -394,7 +398,8 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
|
|
|
/* The instance is out of sync, try other buffer if other
|
|
|
* buffer is configured, return 0 otherwise. If the instance is
|
|
|
* out of sync, do not update the 'next_rx_buf_to_use' since it
|
|
|
- * will correct on subsequent calls */
|
|
|
+ * will correct on subsequent calls
|
|
|
+ */
|
|
|
if (drvdata->rx_ping_pong != 0)
|
|
|
addr = (void __iomem __force *)((u32 __force)addr ^
|
|
|
XEL_BUFFER_OFFSET);
|
|
@@ -408,13 +413,15 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
|
|
|
return 0; /* No data was available */
|
|
|
}
|
|
|
|
|
|
- /* Get the protocol type of the ethernet frame that arrived */
|
|
|
+ /* Get the protocol type of the ethernet frame that arrived
|
|
|
+ */
|
|
|
proto_type = ((ntohl(xemaclite_readl(addr + XEL_HEADER_OFFSET +
|
|
|
XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
|
|
|
XEL_RPLR_LENGTH_MASK);
|
|
|
|
|
|
/* Check if received ethernet frame is a raw ethernet frame
|
|
|
- * or an IP packet or an ARP packet */
|
|
|
+ * or an IP packet or an ARP packet
|
|
|
+ */
|
|
|
if (proto_type > ETH_DATA_LEN) {
|
|
|
|
|
|
if (proto_type == ETH_P_IP) {
|
|
@@ -430,7 +437,8 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
|
|
|
length = XEL_ARP_PACKET_SIZE + ETH_HLEN + ETH_FCS_LEN;
|
|
|
else
|
|
|
/* Field contains type other than IP or ARP, use max
|
|
|
- * frame size and let user parse it */
|
|
|
+ * frame size and let user parse it
|
|
|
+ */
|
|
|
length = ETH_FRAME_LEN + ETH_FCS_LEN;
|
|
|
} else
|
|
|
/* Use the length in the frame, plus the header and trailer */
|
|
@@ -440,7 +448,7 @@ static u16 xemaclite_recv_data(struct net_local *drvdata, u8 *data, int maxlen)
|
|
|
length = maxlen;
|
|
|
|
|
|
/* Read from the EmacLite device */
|
|
|
- xemaclite_aligned_read((u32 __force *) (addr + XEL_RXBUFF_OFFSET),
|
|
|
+ xemaclite_aligned_read((u32 __force *)(addr + XEL_RXBUFF_OFFSET),
|
|
|
data, length);
|
|
|
|
|
|
/* Acknowledge the frame */
|
|
@@ -471,7 +479,7 @@ static void xemaclite_update_address(struct net_local *drvdata,
|
|
|
/* Determine the expected Tx buffer address */
|
|
|
addr = drvdata->base_addr + drvdata->next_tx_buf_to_use;
|
|
|
|
|
|
- xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
|
|
|
+ xemaclite_aligned_write(address_ptr, (u32 __force *)addr, ETH_ALEN);
|
|
|
|
|
|
xemaclite_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
|
|
|
|
|
@@ -488,7 +496,7 @@ static void xemaclite_update_address(struct net_local *drvdata,
|
|
|
/**
|
|
|
* xemaclite_set_mac_address - Set the MAC address for this device
|
|
|
* @dev: Pointer to the network device instance
|
|
|
- * @addr: Void pointer to the sockaddr structure
|
|
|
+ * @address: Void pointer to the sockaddr structure
|
|
|
*
|
|
|
* This function copies the HW address from the sockaddr strucutre to the
|
|
|
* net_device structure and updates the address in HW.
|
|
@@ -564,19 +572,19 @@ static void xemaclite_tx_handler(struct net_device *dev)
|
|
|
struct net_local *lp = netdev_priv(dev);
|
|
|
|
|
|
dev->stats.tx_packets++;
|
|
|
- if (lp->deferred_skb) {
|
|
|
- if (xemaclite_send_data(lp,
|
|
|
- (u8 *) lp->deferred_skb->data,
|
|
|
- lp->deferred_skb->len) != 0)
|
|
|
- return;
|
|
|
- else {
|
|
|
- dev->stats.tx_bytes += lp->deferred_skb->len;
|
|
|
- dev_kfree_skb_irq(lp->deferred_skb);
|
|
|
- lp->deferred_skb = NULL;
|
|
|
- netif_trans_update(dev); /* prevent tx timeout */
|
|
|
- netif_wake_queue(dev);
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
+ if (!lp->deferred_skb)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (xemaclite_send_data(lp, (u8 *)lp->deferred_skb->data,
|
|
|
+ lp->deferred_skb->len))
|
|
|
+ return;
|
|
|
+
|
|
|
+ dev->stats.tx_bytes += lp->deferred_skb->len;
|
|
|
+ dev_kfree_skb_irq(lp->deferred_skb);
|
|
|
+ lp->deferred_skb = NULL;
|
|
|
+ netif_trans_update(dev); /* prevent tx timeout */
|
|
|
+ netif_wake_queue(dev);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -602,18 +610,18 @@ static void xemaclite_rx_handler(struct net_device *dev)
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- /*
|
|
|
- * A new skb should have the data halfword aligned, but this code is
|
|
|
+ /* A new skb should have the data halfword aligned, but this code is
|
|
|
* here just in case that isn't true. Calculate how many
|
|
|
* bytes we should reserve to get the data to start on a word
|
|
|
- * boundary */
|
|
|
+ * boundary
|
|
|
+ */
|
|
|
align = BUFFER_ALIGN(skb->data);
|
|
|
if (align)
|
|
|
skb_reserve(skb, align);
|
|
|
|
|
|
skb_reserve(skb, 2);
|
|
|
|
|
|
- len = xemaclite_recv_data(lp, (u8 *) skb->data, len);
|
|
|
+ len = xemaclite_recv_data(lp, (u8 *)skb->data, len);
|
|
|
|
|
|
if (!len) {
|
|
|
dev->stats.rx_errors++;
|
|
@@ -639,6 +647,8 @@ static void xemaclite_rx_handler(struct net_device *dev)
|
|
|
* @dev_id: Void pointer to the network device instance used as callback
|
|
|
* reference
|
|
|
*
|
|
|
+ * Return: IRQ_HANDLED
|
|
|
+ *
|
|
|
* This function handles the Tx and Rx interrupts of the EmacLite device.
|
|
|
*/
|
|
|
static irqreturn_t xemaclite_interrupt(int irq, void *dev_id)
|
|
@@ -706,8 +716,8 @@ static int xemaclite_mdio_wait(struct net_local *lp)
|
|
|
unsigned long end = jiffies + 2;
|
|
|
|
|
|
/* wait for the MDIO interface to not be busy or timeout
|
|
|
- after some time.
|
|
|
- */
|
|
|
+ * after some time.
|
|
|
+ */
|
|
|
while (xemaclite_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
|
|
|
XEL_MDIOCTRL_MDIOSTS_MASK) {
|
|
|
if (time_before_eq(end, jiffies)) {
|
|
@@ -757,7 +767,7 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg)
|
|
|
rc = xemaclite_readl(lp->base_addr + XEL_MDIORD_OFFSET);
|
|
|
|
|
|
dev_dbg(&lp->ndev->dev,
|
|
|
- "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
|
|
|
+ "%s(phy_id=%i, reg=%x) == %x\n", __func__,
|
|
|
phy_id, reg, rc);
|
|
|
|
|
|
return rc;
|
|
@@ -772,6 +782,8 @@ static int xemaclite_mdio_read(struct mii_bus *bus, int phy_id, int reg)
|
|
|
*
|
|
|
* This function waits till the device is ready to accept a new MDIO
|
|
|
* request and then writes the val to the MDIO Write Data register.
|
|
|
+ *
|
|
|
+ * Return: 0 upon success or a negative error upon failure
|
|
|
*/
|
|
|
static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
|
|
|
u16 val)
|
|
@@ -780,7 +792,7 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
|
|
|
u32 ctrl_reg;
|
|
|
|
|
|
dev_dbg(&lp->ndev->dev,
|
|
|
- "xemaclite_mdio_write(phy_id=%i, reg=%x, val=%x)\n",
|
|
|
+ "%s(phy_id=%i, reg=%x, val=%x)\n", __func__,
|
|
|
phy_id, reg, val);
|
|
|
|
|
|
if (xemaclite_mdio_wait(lp))
|
|
@@ -805,7 +817,7 @@ static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
|
|
|
/**
|
|
|
* xemaclite_mdio_setup - Register mii_bus for the Emaclite device
|
|
|
* @lp: Pointer to the Emaclite device private data
|
|
|
- * @ofdev: Pointer to OF device structure
|
|
|
+ * @dev: Pointer to OF device structure
|
|
|
*
|
|
|
* This function enables MDIO bus in the Emaclite device and registers a
|
|
|
* mii_bus.
|
|
@@ -905,6 +917,9 @@ static void xemaclite_adjust_link(struct net_device *ndev)
|
|
|
* This function sets the MAC address, requests an IRQ and enables interrupts
|
|
|
* for the Emaclite device and starts the Tx queue.
|
|
|
* It also connects to the phy device, if MDIO is included in Emaclite device.
|
|
|
+ *
|
|
|
+ * Return: 0 on success. -ENODEV, if PHY cannot be connected.
|
|
|
+ * Non-zero error value on failure.
|
|
|
*/
|
|
|
static int xemaclite_open(struct net_device *dev)
|
|
|
{
|
|
@@ -975,6 +990,8 @@ static int xemaclite_open(struct net_device *dev)
|
|
|
* This function stops the Tx queue, disables interrupts and frees the IRQ for
|
|
|
* the Emaclite device.
|
|
|
* It also disconnects the phy device associated with the Emaclite device.
|
|
|
+ *
|
|
|
+ * Return: 0, always.
|
|
|
*/
|
|
|
static int xemaclite_close(struct net_device *dev)
|
|
|
{
|
|
@@ -1017,10 +1034,11 @@ static int xemaclite_send(struct sk_buff *orig_skb, struct net_device *dev)
|
|
|
new_skb = orig_skb;
|
|
|
|
|
|
spin_lock_irqsave(&lp->reset_lock, flags);
|
|
|
- if (xemaclite_send_data(lp, (u8 *) new_skb->data, len) != 0) {
|
|
|
+ if (xemaclite_send_data(lp, (u8 *)new_skb->data, len) != 0) {
|
|
|
/* If the Emaclite Tx buffer is busy, stop the Tx queue and
|
|
|
* defer the skb for transmission during the ISR, after the
|
|
|
- * current transmission is complete */
|
|
|
+ * current transmission is complete
|
|
|
+ */
|
|
|
netif_stop_queue(dev);
|
|
|
lp->deferred_skb = new_skb;
|
|
|
/* Take the time stamp now, since we can't do this in an ISR. */
|
|
@@ -1052,13 +1070,12 @@ static bool get_bool(struct platform_device *ofdev, const char *s)
|
|
|
{
|
|
|
u32 *p = (u32 *)of_get_property(ofdev->dev.of_node, s, NULL);
|
|
|
|
|
|
- if (p) {
|
|
|
- return (bool)*p;
|
|
|
- } else {
|
|
|
- dev_warn(&ofdev->dev, "Parameter %s not found,"
|
|
|
- "defaulting to false\n", s);
|
|
|
+ if (!p) {
|
|
|
+ dev_warn(&ofdev->dev, "Parameter %s not found, defaulting to false\n", s);
|
|
|
return false;
|
|
|
}
|
|
|
+
|
|
|
+ return (bool)*p;
|
|
|
}
|
|
|
|
|
|
static const struct net_device_ops xemaclite_netdev_ops;
|
|
@@ -1066,7 +1083,6 @@ static const struct net_device_ops xemaclite_netdev_ops;
|
|
|
/**
|
|
|
* xemaclite_of_probe - Probe method for the Emaclite device.
|
|
|
* @ofdev: Pointer to OF device structure
|
|
|
- * @match: Pointer to the structure used for matching a device
|
|
|
*
|
|
|
* This function probes for the Emaclite device in the device tree.
|
|
|
* It initializes the driver data structure and the hardware, sets the MAC
|