Commit abf79225 authored by Alessandro Rubini's avatar Alessandro Rubini

wr_minic.c: whitespace and indentation cleanup

parent 4dfe582f
......@@ -57,8 +57,10 @@
#define RX_OOB_SIZE 6
#define REFCLK_FREQ 125000000
// extracts the values of TS rising and falling edge counters from the descriptor header
/*
* Extracts the values of TS rising and falling edge counters
* from the descriptor header
*/
#define EXPLODE_WR_TIMESTAMP(raw, rc, fc) \
rc = (raw) & 0xfffffff; \
fc = (raw >> 28) & 0xf;
......@@ -74,40 +76,39 @@ struct tx_timestamp {
};
struct wr_minic {
void __iomem *base; // base address of the Minic+Packet RAM+Endpoint combo
void __iomem *minic_regs; // base address of the miNIC registers
void __iomem *ep_regs; // base address of the Endpoint registers
void __iomem *pbuf; // base address of the Packet RAM
void __iomem *ppsg; // base address of the PPS generator
void __iomem *base; // address of the Minic+RAM+Endpoint combo
void __iomem *minic_regs; // address of the miNIC registers
void __iomem *ep_regs; // address of the Endpoint registers
void __iomem *pbuf; // address of the Packet RAM
void __iomem *ppsg; // address of the PPS generator
spinlock_t lock;
spinlock_t lock;
int tx_hwtstamp_enable;
int rx_hwtstamp_enable;
int tx_hwtstamp_enable;
int rx_hwtstamp_enable;
u16 tx_hwtstamp_oob;
u16 tx_hwtstamp_oob;
struct tx_timestamp tx_tstable[MINIC_TX_MAX_TS];
struct tx_timestamp tx_tstable[MINIC_TX_MAX_TS];
struct platform_device *pdev;
struct device *dev;
struct net_device *netdev;
struct net_device_stats stats;
struct napi_struct napi;
struct sk_buff *current_skb;
struct timer_list link_timer;
struct platform_device *pdev;
struct device *dev;
struct net_device *netdev;
struct net_device_stats stats;
struct napi_struct napi;
struct sk_buff *current_skb;
struct timer_list link_timer;
unsigned int rx_head, rx_avail, rx_base, rx_size;
unsigned int tx_head, tx_avail, tx_base, tx_size;
unsigned int rx_head, rx_avail, rx_base, rx_size;
unsigned int tx_head, tx_avail, tx_base, tx_size;
bool synced;
bool syncing_counters;
int iface_up;
bool synced;
bool syncing_counters;
int iface_up;
u32 cur_rx_desc;
u32 cur_rx_desc;
struct mii_if_info mii;
struct mii_if_info mii;
};
MODULE_DESCRIPTION("White Rabbit miNIC driver");
......@@ -137,19 +138,25 @@ MODULE_ALIAS("platform:wr-minic");
// reads an MDIO register
static int phy_read(struct net_device *dev, int phy_id, int location)
{
struct wr_minic *nic = netdev_priv(dev);
struct wr_minic *nic = netdev_priv(dev);
endpoint_writel(nic, EP_REG_MDIO_CR, EP_MDIO_CR_ADDR_W(location));
while( (endpoint_readl(nic, EP_REG_MDIO_SR) & EP_MDIO_SR_READY) == 0);
return EP_MDIO_SR_RDATA_R(endpoint_readl(nic, EP_REG_MDIO_SR));
endpoint_writel(nic, EP_REG_MDIO_CR, EP_MDIO_CR_ADDR_W(location));
while( (endpoint_readl(nic, EP_REG_MDIO_SR) & EP_MDIO_SR_READY) == 0)
;
return EP_MDIO_SR_RDATA_R(endpoint_readl(nic, EP_REG_MDIO_SR));
}
static void phy_write(struct net_device *dev, int phy_id, int location, int value)
static void phy_write(struct net_device *dev, int phy_id, int location,
int value)
{
struct wr_minic *nic = netdev_priv(dev);
endpoint_writel(nic, EP_REG_MDIO_CR, EP_MDIO_CR_ADDR_W(location) | EP_MDIO_CR_DATA_W(value)| EP_MDIO_CR_RW);
while( (endpoint_readl(nic, EP_REG_MDIO_SR) & EP_MDIO_SR_READY) == 0);
struct wr_minic *nic = netdev_priv(dev);
endpoint_writel(nic, EP_REG_MDIO_CR,
EP_MDIO_CR_ADDR_W(location)
| EP_MDIO_CR_DATA_W(value)
| EP_MDIO_CR_RW);
while( (endpoint_readl(nic, EP_REG_MDIO_SR) & EP_MDIO_SR_READY) == 0)
;
}
......@@ -162,7 +169,8 @@ static int minic_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
ret = mii_ethtool_gset(&lp->mii, cmd);
spin_unlock_irq(&lp->lock);
cmd->supported= SUPPORTED_FIBRE | SUPPORTED_Autoneg| SUPPORTED_1000baseKX_Full;
cmd->supported= SUPPORTED_FIBRE | SUPPORTED_Autoneg
| SUPPORTED_1000baseKX_Full;
cmd->advertising = ADVERTISED_1000baseKX_Full | ADVERTISED_Autoneg;
cmd->port = PORT_FIBRE;
cmd->speed = SPEED_1000;
......@@ -197,11 +205,13 @@ static int minic_nwayreset(struct net_device *dev)
return ret;
}
static void minic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
static void minic_get_drvinfo(struct net_device *dev,
struct ethtool_drvinfo *info)
{
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info));
strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
strlcpy(info->version, DRV_VERSION, sizeof(info->version));
strlcpy(info->bus_info, dev_name(dev->dev.parent),
sizeof(info->bus_info));
}
static const struct ethtool_ops minic_ethtool_ops = {
......@@ -216,49 +226,50 @@ static const struct ethtool_ops minic_ethtool_ops = {
// use in locked context, please
static void minic_ppsg_read_time(struct wr_minic *nic, u32 *cntr, u64 *utc)
{
uint32_t cyc_before, cyc_after;
uint32_t utc_lo, utc_hi;
for(;;)
{
cyc_before =ppsg_readl(nic, PPSG_REG_CNTR_NSEC) & 0xfffffff;
utc_lo = ppsg_readl(nic, PPSG_REG_CNTR_UTCLO) ;
utc_hi = ppsg_readl(nic, PPSG_REG_CNTR_UTCHI) & 0xff;
cyc_after = ppsg_readl(nic, PPSG_REG_CNTR_NSEC) & 0xfffffff;
// there was an UTC transition. (nanosecond counter overflow). read the value again.
if(cyc_after < REFCLK_FREQ/4 && cyc_before > (REFCLK_FREQ - REFCLK_FREQ/4))
continue;
else {
if(utc) *utc = (u64)utc_lo | (u64)utc_hi << 32;
if(cntr) *cntr = cyc_after;
return;
}
}
uint32_t cyc_before, cyc_after;
uint32_t utc_lo, utc_hi;
for(;;) {
cyc_before =ppsg_readl(nic, PPSG_REG_CNTR_NSEC) & 0xfffffff;
utc_lo = ppsg_readl(nic, PPSG_REG_CNTR_UTCLO) ;
utc_hi = ppsg_readl(nic, PPSG_REG_CNTR_UTCHI) & 0xff;
cyc_after = ppsg_readl(nic, PPSG_REG_CNTR_NSEC) & 0xfffffff;
// there was an UTC transition. (nanosecond counter overflow),
// read the value again.
if(cyc_after < REFCLK_FREQ/4
&& cyc_before > (REFCLK_FREQ - REFCLK_FREQ/4)) {
continue;
} else {
if(utc) *utc = (u64)utc_lo | (u64)utc_hi << 32;
if(cntr) *cntr = cyc_after;
return;
}
}
}
static inline u32 minic_ppsg_get_nsecs(struct wr_minic *nic)
{
return ppsg_readl(nic, PPSG_REG_CNTR_NSEC) & 0xfffffff;
return ppsg_readl(nic, PPSG_REG_CNTR_NSEC) & 0xfffffff;
}
static void minic_disable_irq(struct wr_minic *nic, u32 mask)
{
// dev_dbg(nic->dev, "wr_disable_irq() - mask %x\n", mask);
minic_writel(nic, MINIC_REG_EIC_IDR, mask);
// dev_dbg(nic->dev, "wr_disable_irq() - mask %x\n", mask);
minic_writel(nic, MINIC_REG_EIC_IDR, mask);
}
static void minic_enable_irq(struct wr_minic *nic, u32 mask)
{
// dev_dbg(nic->dev, "wr_enable_irq() - mask %x\n", mask);
minic_writel(nic, MINIC_REG_EIC_IER, mask);
// dev_dbg(nic->dev, "wr_enable_irq() - mask %x\n", mask);
minic_writel(nic, MINIC_REG_EIC_IER, mask);
}
static void minic_clear_irq(struct wr_minic *nic, u32 mask)
{
minic_writel(nic, MINIC_REG_EIC_ISR, mask);
minic_writel(nic, MINIC_REG_EIC_ISR, mask);
}
static struct net_device_stats *minic_get_stats(struct net_device *netdev)
......@@ -272,12 +283,12 @@ static struct net_device_stats *minic_get_stats(struct net_device *netdev)
static void minic_new_rx_buffer(struct wr_minic *nic)
{
nic->rx_head = nic->rx_base;
nic->rx_head = nic->rx_base;
minic_writel(nic, MINIC_REG_MCR, 0);
minic_writel(nic, MINIC_REG_RX_ADDR, nic->rx_base);
minic_writel(nic, MINIC_REG_RX_AVAIL, (nic->rx_size - MINIC_MTU) >> 2);
minic_writel(nic, MINIC_REG_MCR, MINIC_MCR_RX_EN);
minic_writel(nic, MINIC_REG_MCR, 0);
minic_writel(nic, MINIC_REG_RX_ADDR, nic->rx_base);
minic_writel(nic, MINIC_REG_RX_AVAIL, (nic->rx_size - MINIC_MTU) >> 2);
minic_writel(nic, MINIC_REG_MCR, MINIC_MCR_RX_EN);
}
......@@ -285,393 +296,383 @@ static void minic_new_tx_buffer(struct wr_minic *nic)
{
nic->tx_head = nic->tx_base;
nic->tx_avail = (nic->tx_size - MINIC_MTU) >> 2;
minic_writel(nic, MINIC_REG_TX_ADDR, nic->tx_base);
}
static int minic_rx_frame(struct wr_minic *nic)
{
struct net_device *netdev = nic->netdev;
struct sk_buff *skb;
u32 __iomem *rx_head;
u32 *tmp_ptr;
u32 payload_size, num_words;
u32 desc_hdr;
u32 rx_addr_cur;
u32 rx_oob;
u32 tmp_buf[(MINIC_MTU >> 2) + 8];
int i;
/* get the address of the latest RX descriptor */
rx_addr_cur = minic_readl(nic, MINIC_REG_RX_ADDR) & 0xffffff;
if(rx_addr_cur < nic->rx_head) /* nothing new in the buffer? */
return 1;
rx_head = nic->pbuf + nic->rx_head;
desc_hdr = __raw_readl(rx_head++); /* read the 32-bit descriptor header */
if(!RX_DESC_VALID(desc_hdr)) /* invalid descriptor? Weird, the RX_ADDR seems to be saying something different. Ignore the packet and purge the RX buffer. */
{
dev_info(nic->dev, "%s: weird, invalid RX descriptor (%x, head %x)", __func__, desc_hdr, (unsigned int) rx_head-1);
minic_new_rx_buffer(nic);
return 0;
}
struct net_device *netdev = nic->netdev;
struct sk_buff *skb;
u32 __iomem *rx_head;
u32 *tmp_ptr;
u32 payload_size, num_words;
u32 desc_hdr;
u32 rx_addr_cur;
u32 rx_oob;
u32 tmp_buf[(MINIC_MTU >> 2) + 8];
int i;
/* get the address of the latest RX descriptor */
rx_addr_cur = minic_readl(nic, MINIC_REG_RX_ADDR) & 0xffffff;
if(rx_addr_cur < nic->rx_head) /* nothing new in the buffer? */
return 1;
rx_head = nic->pbuf + nic->rx_head;
desc_hdr = __raw_readl(rx_head++); /* read 32-bit descriptor header */
if(!RX_DESC_VALID(desc_hdr)) {
/*
* invalid descriptor? Weird, the RX_ADDR seems
* to be saying something different. Ignore the packet
* and purge the RX buffer.
*/
dev_info(nic->dev, "%s: weird, invalid RX descriptor "
"(%x, head %x)", __func__, desc_hdr,
(unsigned int) rx_head-1);
minic_new_rx_buffer(nic);
return 0;
}
// if(RX_DESC_HAS_OOB(desc_hdr))
payload_size = RX_DESC_SIZE(desc_hdr);
payload_size = RX_DESC_SIZE(desc_hdr);
num_words = (payload_size + 3) >> 2;
num_words = (payload_size + 3) >> 2;
/* valid packet */
if(!RX_DESC_ERROR(desc_hdr))
{
skb = netdev_alloc_skb(netdev, payload_size + 9);
if (unlikely(skb == NULL)) {
if (net_ratelimit())
dev_warn(nic->dev, "-ENOMEM - packet dropped\n");
return 0;
}
/* Make the IP header word-aligned (the ethernet header is 14 bytes) */
skb_reserve(skb, 2);
for(i=num_words, tmp_ptr = tmp_buf;i >=0 ; i--)
*tmp_ptr ++ = __raw_readl(rx_head++);
/* valid packet */
if(!RX_DESC_ERROR(desc_hdr)) {
skb = netdev_alloc_skb(netdev, payload_size + 9);
if (unlikely(skb == NULL)) {
if (net_ratelimit())
dev_warn(nic->dev, "-ENOMEM - pckt dropped\n");
return 0;
}
if(RX_DESC_HAS_OOB(desc_hdr)) // RX timestamping
{
struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
u32 counter_r, counter_f; // timestamp counter values
u32 counter_ppsg; // PPS generator nanosecond counter
u64 utc;
s32 cntr_diff;
/* Make the IP header aligned (the eth header is 14 bytes) */
skb_reserve(skb, 2);
payload_size -= RX_OOB_SIZE;
for(i=num_words, tmp_ptr = tmp_buf;i >=0 ; i--)
*tmp_ptr ++ = __raw_readl(rx_head++);
memcpy(&rx_oob, ((void *)tmp_buf) + payload_size+2, 4);
rx_oob = swab32(rx_oob);
if(RX_DESC_HAS_OOB(desc_hdr)) // RX timestamping
{
struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
u32 counter_r, counter_f; // timestamp counter values
u32 counter_ppsg; // PPS generator nanosecond counter
u64 utc;
s32 cntr_diff;
EXPLODE_WR_TIMESTAMP(rx_oob, counter_r, counter_f);
minic_ppsg_read_time(nic, &counter_ppsg, &utc);
payload_size -= RX_OOB_SIZE;
if(counter_r > (3*REFCLK_FREQ/4) && counter_ppsg < REFCLK_FREQ/4)
utc--;
// fixme: we need to pass the phase value somehow for RX timestamps. For the time being, we pass the R-F counter difference on the MSB of UTC (instead of sign value), so the PTP can detect the valid counter
memcpy(&rx_oob, ((void *)tmp_buf) + payload_size+2, 4);
rx_oob = swab32(rx_oob);
hwts->hwtstamp.tv.sec = (s32)utc & 0x7fffffff ;
EXPLODE_WR_TIMESTAMP(rx_oob, counter_r, counter_f);
minic_ppsg_read_time(nic, &counter_ppsg, &utc);
if(counter_r > (3*REFCLK_FREQ/4)
&& counter_ppsg < REFCLK_FREQ/4)
utc--;
cntr_diff = (counter_r & F_COUNTER_MASK) - counter_f;
/* fixme: we need to pass the phase value somehow
* for RX timestamps. For the time being, we pass
* the R-F counter difference on the MSB of UTC
* (instead of sign value), so the PTP can detect
* the valid counter
*/
if(cntr_diff == 1 || cntr_diff == (-F_COUNTER_MASK))
hwts->hwtstamp.tv.sec |= 0x80000000; // indicated that the rising edge counter is one tick ahead
hwts->hwtstamp.tv.nsec = counter_r * 8;
}
hwts->hwtstamp.tv.sec = (s32)utc & 0x7fffffff;
memcpy(skb_put(skb, payload_size), tmp_buf, payload_size);
/* determine protocol id */
skb->protocol = eth_type_trans(skb, netdev);
/* @fixme ignore the checksum for the time being */
skb->ip_summed = CHECKSUM_UNNECESSARY;
/* update the rx buffer head to point to the next descriptor */
nic->rx_head += ( num_words + 1 ) << 2;
netdev->last_rx = jiffies;
nic->stats.rx_packets++;
nic->stats.rx_bytes += payload_size;
netif_receive_skb(skb);
} else { // RX_DESC_ERROR
nic->stats.rx_errors ++;
nic->rx_head += ( num_words + 1 ) << 2;
}
wmb();
return 0;
}
cntr_diff = (counter_r & F_COUNTER_MASK) - counter_f;
/* the bit says the rising edge cnter is 1tick ahead */
if(cntr_diff == 1 || cntr_diff == (-F_COUNTER_MASK))
hwts->hwtstamp.tv.sec |= 0x80000000;
hwts->hwtstamp.tv.nsec = counter_r * 8;
}
memcpy(skb_put(skb, payload_size), tmp_buf, payload_size);
static int minic_poll_txts_fifo(struct wr_minic *nic, u16 oob_fid, struct skb_shared_hwtstamps *hwts)
{
int i;
/* determine protocol id */
skb->protocol = eth_type_trans(skb, netdev);
u32 dmsr;
int dmtd_phase;
/* @fixme ignore the checksum for the time being */
skb->ip_summed = CHECKSUM_UNNECESSARY;
dmsr = endpoint_readl(nic, EP_REG_DMSR);
/* update the rx buffer head to point to the next descriptor */
nic->rx_head += ( num_words + 1 ) << 2;
if(dmsr & EP_DMSR_PS_RDY)
dmtd_phase = EP_DMSR_PS_VAL_R(dmsr);
else
dmtd_phase = 0;
netdev->last_rx = jiffies;
nic->stats.rx_packets++;
nic->stats.rx_bytes += payload_size;
netif_receive_skb(skb);
} else { // RX_DESC_ERROR
nic->stats.rx_errors ++;
nic->rx_head += ( num_words + 1 ) << 2;
}
wmb();
return 0;
}
// sign-extend, fix the average if its out of range due to jitter
if(dmtd_phase & 0x800000) dmtd_phase |= 0xff000000;
static int minic_poll_txts_fifo(struct wr_minic *nic, u16 oob_fid,
struct skb_shared_hwtstamps *hwts)
{
int i;
// calculate the average
dmtd_phase /= DMTD_AVG_SAMPLES;
u32 dmsr;
int dmtd_phase;
if(dmtd_phase > DMTD_MAX_PHASE) dmtd_phase -= DMTD_MAX_PHASE;
if(dmtd_phase < 0) dmtd_phase += DMTD_MAX_PHASE;
dmsr = endpoint_readl(nic, EP_REG_DMSR);
if(dmsr & EP_DMSR_PS_RDY)
dmtd_phase = EP_DMSR_PS_VAL_R(dmsr);
else
dmtd_phase = 0;
while(!(minic_readl(nic, MINIC_REG_TSFIFO_CSR) & MINIC_TSFIFO_CSR_EMPTY))
{
u32 tsval_raw = minic_readl(nic, MINIC_REG_TSFIFO_R0);
u32 fid = (minic_readl(nic, MINIC_REG_TSFIFO_R1) >> 5) & 0xffff;
u32 counter_r, counter_f; // timestamp counter values
u32 counter_ppsg; // PPS generator nanosecond counter
u64 utc;
struct skb_shared_hwtstamps tsval;
// sign-extend, fix the average if its out of range due to jitter
if(dmtd_phase & 0x800000) dmtd_phase |= 0xff000000;
EXPLODE_WR_TIMESTAMP(tsval_raw, counter_r, counter_f);
// printk("About to read time\n");
// calculate the average
dmtd_phase /= DMTD_AVG_SAMPLES;
if(dmtd_phase > DMTD_MAX_PHASE) dmtd_phase -= DMTD_MAX_PHASE;
if(dmtd_phase < 0) dmtd_phase += DMTD_MAX_PHASE;
minic_ppsg_read_time(nic, &counter_ppsg, &utc);
// printk("After read time\n");
while(!(minic_readl(nic, MINIC_REG_TSFIFO_CSR)
& MINIC_TSFIFO_CSR_EMPTY)) {
u32 tsval_raw = minic_readl(nic, MINIC_REG_TSFIFO_R0);
u32 fid = (minic_readl(nic, MINIC_REG_TSFIFO_R1) >> 5) & 0xffff;
// the timestamp was taken at the end of previous second
// of UTC time, and now we are at the beginning of the next second
if(counter_r > (3*REFCLK_FREQ/4) && counter_ppsg < REFCLK_FREQ/4)
utc--;
u32 counter_r, counter_f; // timestamp counter values
u32 counter_ppsg; // PPS generator nanosecond counter
u64 utc;
struct skb_shared_hwtstamps tsval;
// fixme
tsval.hwtstamp.tv.sec = ((s32)utc & 0x7fffffff);
tsval.hwtstamp.tv.nsec = counter_r * 8;
EXPLODE_WR_TIMESTAMP(tsval_raw, counter_r, counter_f);
for(i = 0; i<MINIC_TX_MAX_TS;i++)
if(!nic->tx_tstable[i].valid)
{
// printk("Addts: fid %d tsval %x\n", fid, tsval);
nic->tx_tstable[i].valid = 1;
nic->tx_tstable[i].ts_val = tsval;
nic->tx_tstable[i].fid = fid;
break;
};
}
// printk("About to read time\n");
minic_ppsg_read_time(nic, &counter_ppsg, &utc);
// printk("queryts: fid %d\n", oob_fid);
// printk("After read time\n");
for(i = 0; i<MINIC_TX_MAX_TS;i++)
if(nic->tx_tstable[i].valid && oob_fid == nic->tx_tstable[i].fid)
{
// printk("GotTS: fid %d\n", oob_fid);
if(hwts)
memcpy(hwts, &nic->tx_tstable[i].ts_val, sizeof(struct skb_shared_hwtstamps));
// the timestamp was taken at the end of previous second
// of UTC time, and now we are at the beg. of the next second
if(counter_r > (3*REFCLK_FREQ/4)
&& counter_ppsg < REFCLK_FREQ/4)
utc--;
nic->tx_tstable[i].valid = 0;
return 0;
};
// fixme
tsval.hwtstamp.tv.sec = ((s32)utc & 0x7fffffff);
tsval.hwtstamp.tv.nsec = counter_r * 8;
for(i = 0; i<MINIC_TX_MAX_TS;i++)
if(!nic->tx_tstable[i].valid) {
// printk("Addts: fid %d tsval %x\n",
// fid, tsval);
nic->tx_tstable[i].valid = 1;
nic->tx_tstable[i].ts_val = tsval;
nic->tx_tstable[i].fid = fid;
break;
}
}
// printk("Missed timestamp...");
return -1;
// printk("queryts: fid %d\n", oob_fid);
for(i = 0; i<MINIC_TX_MAX_TS;i++) {
if(nic->tx_tstable[i].valid && oob_fid
== nic->tx_tstable[i].fid) {
// printk("GotTS: fid %d\n", oob_fid);
if(hwts)
memcpy(hwts, &nic->tx_tstable[i].ts_val,
sizeof(struct skb_shared_hwtstamps));
nic->tx_tstable[i].valid = 0;
return 0;
}
}
// printk("Missed timestamp...");
return -1;
}
static inline void minic_tx_handle_irq(struct wr_minic *nic)
{
struct net_device *netdev = nic->netdev;
struct skb_shared_hwtstamps hwts;
struct skb_shared_hwtstamps *hwoob = skb_hwtstamps(nic->current_skb);
union skb_shared_tx *shtx = skb_tx(nic->current_skb);
struct net_device *netdev = nic->netdev;
unsigned long flags;
u16 oob_tag;
spin_lock_irqsave(&nic->lock, flags);
struct skb_shared_hwtstamps hwts;
struct skb_shared_hwtstamps *hwoob = skb_hwtstamps(nic->current_skb);
union skb_shared_tx *shtx = skb_tx(nic->current_skb);
// this will only work for the NIC directly connected to the endpoint. In case of a switch,
// the packet will reach the output port after being completely transmitted by the NIC (i.e. after the TX interrupt)
if(shtx->in_progress)
{
oob_tag = *(u16 *) hwoob;
if(!minic_poll_txts_fifo(nic, oob_tag, &hwts))
skb_tstamp_tx(nic->current_skb, &hwts);
unsigned long flags;
u16 oob_tag;
}
spin_lock_irqsave(&nic->lock, flags);
dev_kfree_skb_irq(nic->current_skb);
/*
* this will only work for the NIC directly connected to the endpoint.
* In case of a switch, the packet will reach the output port after
* being completely transmitted by the NIC (i.e. after TX interrupt)
*/
if (netif_queue_stopped(nic->netdev))
netif_wake_queue(netdev);
if(shtx->in_progress) {
oob_tag = *(u16 *) hwoob;
if(!minic_poll_txts_fifo(nic, oob_tag, &hwts))
skb_tstamp_tx(nic->current_skb, &hwts);
}
spin_unlock_irqrestore(&nic->lock, flags);
dev_kfree_skb_irq(nic->current_skb);
minic_clear_irq(nic, MINIC_EIC_ISR_TX); // clear the TX interrupt
}
if (netif_queue_stopped(nic->netdev))
netif_wake_queue(netdev);
spin_unlock_irqrestore(&nic->lock, flags);
minic_clear_irq(nic, MINIC_EIC_ISR_TX); // clear the TX interrupt
}
static inline void minic_rx_handle_irq(struct wr_minic *nic)
{
int buf_full;
buf_full = minic_readl(nic, MINIC_REG_MCR) & MINIC_MCR_RX_FULL ? 1 : 0;
int buf_full;
while(!minic_rx_frame(nic));
buf_full = minic_readl(nic, MINIC_REG_MCR) & MINIC_MCR_RX_FULL ? 1 : 0;
if(buf_full)
minic_new_rx_buffer(nic);
while(!minic_rx_frame(nic));
minic_clear_irq(nic, MINIC_EIC_ISR_RX);
if(buf_full)
minic_new_rx_buffer(nic);
minic_clear_irq(nic, MINIC_EIC_ISR_RX);
}
static void minic_interrupt(void *dev_id) // called by MCH VIC driver
{
struct net_device *netdev = dev_id;
struct wr_minic *nic = netdev_priv(netdev);
u32 isr;
struct net_device *netdev = dev_id;
struct wr_minic *nic = netdev_priv(netdev);
u32 isr;
isr = minic_readl(nic, MINIC_REG_EIC_ISR);
isr = minic_readl(nic, MINIC_REG_EIC_ISR);
if (isr & MINIC_EIC_ISR_TX)
minic_tx_handle_irq(nic);
if (isr & MINIC_EIC_ISR_RX)
minic_rx_handle_irq(nic);
if (isr & MINIC_EIC_ISR_TX)
minic_tx_handle_irq(nic);
if (isr & MINIC_EIC_ISR_RX)
minic_rx_handle_irq(nic);
}
static int minic_hw_tx(struct wr_minic *nic, char *data, unsigned size,
u16 tx_oob_val)
{
u32 __iomem *dst, *dptr;
u32 nwords;
u32 mcr;
int i;
u32 pkt_buf[(MINIC_MTU >> 2) + 4];
nwords = ((size + 1) >> 1) - 1;
static int minic_hw_tx(struct wr_minic *nic, char *data, unsigned size, u16 tx_oob_val)
{
u32 __iomem *dst, *dptr;
u32 nwords;
u32 mcr;
int i;
u32 pkt_buf[(MINIC_MTU >> 2) + 4];
nwords = ((size + 1) >> 1) - 1;