static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int numPages, poll_count, status; unsigned long flags; DBG(3, "%s: %s\n", dev->name, __func__); BUG_ON(lp->pending_tx_skb != NULL); numPages = ((skb->len & ~1) + (6 - 1)) >> 8; if (unlikely(numPages > 7)) { printk("%s: Far too big packet error.\n", dev->name); dev->stats.tx_errors++; dev->stats.tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; } smc_special_lock(&lp->lock, flags); SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages); poll_count = MEMORY_WAIT_TIME; do { status = SMC_GET_INT(lp); if (status & IM_ALLOC_INT) { SMC_ACK_INT(lp, IM_ALLOC_INT); break; } } while (--poll_count); smc_special_unlock(&lp->lock, flags); lp->pending_tx_skb = skb; if (!poll_count) { netif_stop_queue(dev); DBG(2, "%s: TX memory allocation deferred.\n", dev->name); SMC_ENABLE_INT(lp, IM_ALLOC_INT); } else { smc_hardware_send_pkt((unsigned long)dev); } return NETDEV_TX_OK; }
/* * Since I am not sure if I will have enough room in the chip's ram * to store the packet, I call this routine which either sends it * now, or set the card to generates an interrupt when ready * for the packet. */ static int smc_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; unsigned int numPages, poll_count, status; unsigned long flags; DBG(3, "%s: %s\n", dev->name, __func__); BUG_ON(lp->pending_tx_skb != NULL); /* * The MMU wants the number of pages to be the number of 256 bytes * 'pages', minus 1 (since a packet can't ever have 0 pages :)) * * The 91C111 ignores the size bits, but earlier models don't. * * Pkt size for allocating is data length +6 (for additional status * words, length and ctl) * * If odd size then last byte is included in ctl word. */ numPages = ((skb->len & ~1) + (6 - 1)) >> 8; if (unlikely(numPages > 7)) { printk("%s: Far too big packet error.\n", dev->name); dev->stats.tx_errors++; dev->stats.tx_dropped++; dev_kfree_skb(skb); return NETDEV_TX_OK; } smc_special_lock(&lp->lock, flags); /* now, try to allocate the memory */ SMC_SET_MMU_CMD(lp, MC_ALLOC | numPages); /* * Poll the chip for a short amount of time in case the * allocation succeeds quickly. */ poll_count = MEMORY_WAIT_TIME; do { status = SMC_GET_INT(lp); if (status & IM_ALLOC_INT) { SMC_ACK_INT(lp, IM_ALLOC_INT); break; } } while (--poll_count); smc_special_unlock(&lp->lock, flags); lp->pending_tx_skb = skb; if (!poll_count) { /* oh well, wait until the chip finds memory later */ netif_stop_queue(dev); DBG(2, "%s: TX memory allocation deferred.\n", dev->name); SMC_ENABLE_INT(lp, IM_ALLOC_INT); } else { /* * Allocation succeeded: push packet to the chip's own memory * immediately. */ smc_hardware_send_pkt((unsigned long)dev); } return NETDEV_TX_OK; }
static void smc_hardware_send_pkt(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; struct sk_buff *skb; unsigned int packet_no, len; unsigned char *buf; unsigned long flags; DBG(3, "%s: %s\n", dev->name, __func__); if (!smc_special_trylock(&lp->lock, flags)) { netif_stop_queue(dev); tasklet_schedule(&lp->tx_task); return; } skb = lp->pending_tx_skb; if (unlikely(!skb)) { smc_special_unlock(&lp->lock, flags); return; } lp->pending_tx_skb = NULL; packet_no = SMC_GET_AR(lp); if (unlikely(packet_no & AR_FAILED)) { printk("%s: Memory allocation failed.\n", dev->name); dev->stats.tx_errors++; dev->stats.tx_fifo_errors++; smc_special_unlock(&lp->lock, flags); goto done; } SMC_SET_PN(lp, packet_no); SMC_SET_PTR(lp, PTR_AUTOINC); buf = skb->data; len = skb->len; DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n", dev->name, packet_no, len, len, buf); PRINT_PKT(buf, len); SMC_PUT_PKT_HDR(lp, 0, len + 6); SMC_PUSH_DATA(lp, buf, len & ~1); SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp)); if (THROTTLE_TX_PKTS) netif_stop_queue(dev); SMC_SET_MMU_CMD(lp, MC_ENQUEUE); smc_special_unlock(&lp->lock, flags); dev->trans_start = jiffies; dev->stats.tx_packets++; dev->stats.tx_bytes += len; SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT); done: if (!THROTTLE_TX_PKTS) netif_wake_queue(dev); dev_kfree_skb(skb); }
/* * This is called to actually send a packet to the chip. */ static void smc_hardware_send_pkt(unsigned long data) { struct net_device *dev = (struct net_device *)data; struct smc_local *lp = netdev_priv(dev); void __iomem *ioaddr = lp->base; struct sk_buff *skb; unsigned int packet_no, len; unsigned char *buf; unsigned long flags; DBG(3, "%s: %s\n", dev->name, __func__); if (!smc_special_trylock(&lp->lock, flags)) { netif_stop_queue(dev); tasklet_schedule(&lp->tx_task); return; } skb = lp->pending_tx_skb; if (unlikely(!skb)) { smc_special_unlock(&lp->lock, flags); return; } lp->pending_tx_skb = NULL; packet_no = SMC_GET_AR(lp); if (unlikely(packet_no & AR_FAILED)) { printk("%s: Memory allocation failed.\n", dev->name); dev->stats.tx_errors++; dev->stats.tx_fifo_errors++; smc_special_unlock(&lp->lock, flags); goto done; } /* point to the beginning of the packet */ SMC_SET_PN(lp, packet_no); SMC_SET_PTR(lp, PTR_AUTOINC); buf = skb->data; len = skb->len; DBG(2, "%s: TX PNR 0x%x LENGTH 0x%04x (%d) BUF 0x%p\n", dev->name, packet_no, len, len, buf); PRINT_PKT(buf, len); /* * Send the packet length (+6 for status words, length, and ctl. * The card will pad to 64 bytes with zeroes if packet is too small. */ SMC_PUT_PKT_HDR(lp, 0, len + 6); /* send the actual data */ SMC_PUSH_DATA(lp, buf, len & ~1); /* Send final ctl word with the last byte if there is one */ SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG(lp)); /* * If THROTTLE_TX_PKTS is set, we stop the queue here. This will * have the effect of having at most one packet queued for TX * in the chip's memory at all time. * * If THROTTLE_TX_PKTS is not set then the queue is stopped only * when memory allocation (MC_ALLOC) does not succeed right away. */ if (THROTTLE_TX_PKTS) netif_stop_queue(dev); /* queue the packet for TX */ SMC_SET_MMU_CMD(lp, MC_ENQUEUE); smc_special_unlock(&lp->lock, flags); dev->trans_start = jiffies; dev->stats.tx_packets++; dev->stats.tx_bytes += len; SMC_ENABLE_INT(lp, IM_TX_INT | IM_TX_EMPTY_INT); done: if (!THROTTLE_TX_PKTS) netif_wake_queue(dev); dev_kfree_skb(skb); }