#define SGE_FREEL_REFILL_THRESH 16
#define SGE_RESPQ_E_N 1024
#define SGE_INTRTIMER_NRES 1000
-#define SGE_RX_COPY_THRES 256
#define SGE_RX_SM_BUF_SIZE 1536
#define SGE_TX_DESC_MAX_PLEN 16384
-# define SGE_RX_DROP_THRES 2
-
#define SGE_RESPQ_REPLENISH_THRES (SGE_RESPQ_E_N / 4)
/*
*/
#define TX_RECLAIM_PERIOD (HZ / 4)
-#ifndef NET_IP_ALIGN
-# define NET_IP_ALIGN 2
-#endif
-
#define M_CMD_LEN 0x7fffffff
#define V_CMD_LEN(v) (v)
#define G_CMD_LEN(v) ((v) & M_CMD_LEN)
*
* Interrupts are handled by a single CPU and it is likely that on a MP system
* the application is migrated to another CPU. In that scenario, we try to
- * seperate the RX(in irq context) and TX state in order to decrease memory
+ * separate the RX(in irq context) and TX state in order to decrease memory
* contention.
*/
struct sge {
struct sk_buff *espibug_skb[MAX_NPORTS];
u32 sge_control; /* shadow value of sge control reg */
struct sge_intr_counts stats;
- struct sge_port_stats *port_stats[MAX_NPORTS];
+ struct sge_port_stats __percpu *port_stats[MAX_NPORTS];
struct sched *tx_sched;
struct cmdQ cmdQ[SGE_CMDQ_N] ____cacheline_aligned_in_smp;
};
return max_avail_segs * (p->mtu - 40);
}
+#if 0
+
/*
* t1_sched_max_avail_bytes() tells the scheduler the maximum amount of
* data that can be pushed per port.
t1_sched_update_parms(sge, port, 0, 0);
}
+#endif /* 0 */
+
/*
* get_clock() implements a ns clock (see ktime_get)
q->size = p->freelQ_size[i];
q->dma_offset = sge->rx_pkt_pad ? 0 : NET_IP_ALIGN;
size = sizeof(struct freelQ_e) * q->size;
- q->entries = (struct freelQ_e *)
- pci_alloc_consistent(pdev, size, &q->dma_addr);
+ q->entries = pci_alloc_consistent(pdev, size, &q->dma_addr);
if (!q->entries)
goto err_no_mem;
- memset(q->entries, 0, size);
+
size = sizeof(struct freelQ_ce) * q->size;
q->centries = kzalloc(size, GFP_KERNEL);
if (!q->centries)
sge->respQ.size = SGE_RESPQ_E_N;
sge->respQ.credits = 0;
size = sizeof(struct respQ_e) * sge->respQ.size;
- sge->respQ.entries = (struct respQ_e *)
+ sge->respQ.entries =
pci_alloc_consistent(pdev, size, &sge->respQ.dma_addr);
if (!sge->respQ.entries)
goto err_no_mem;
- memset(sge->respQ.entries, 0, size);
return 0;
err_no_mem:
q->in_use -= n;
ce = &q->centries[cidx];
while (n--) {
- if (q->sop) {
- if (likely(pci_unmap_len(ce, dma_len))) {
- pci_unmap_single(pdev,
- pci_unmap_addr(ce, dma_addr),
- pci_unmap_len(ce, dma_len),
- PCI_DMA_TODEVICE);
+ if (likely(pci_unmap_len(ce, dma_len))) {
+ pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_TODEVICE);
+ if (q->sop)
q->sop = 0;
- }
- } else {
- if (likely(pci_unmap_len(ce, dma_len))) {
- pci_unmap_page(pdev, pci_unmap_addr(ce, dma_addr),
- pci_unmap_len(ce, dma_len),
- PCI_DMA_TODEVICE);
- }
}
if (ce->skb) {
dev_kfree_skb_any(ce->skb);
q->stop_thres = 0;
spin_lock_init(&q->lock);
size = sizeof(struct cmdQ_e) * q->size;
- q->entries = (struct cmdQ_e *)
- pci_alloc_consistent(pdev, size, &q->dma_addr);
+ q->entries = pci_alloc_consistent(pdev, size, &q->dma_addr);
if (!q->entries)
goto err_no_mem;
- memset(q->entries, 0, size);
+
size = sizeof(struct cmdQ_ce) * q->size;
q->centries = kzalloc(size, GFP_KERNEL);
if (!q->centries)
skb_reserve(skb, q->dma_offset);
mapping = pci_map_single(pdev, skb->data, dma_len,
PCI_DMA_FROMDEVICE);
+ skb_reserve(skb, sge->rx_pkt_pad);
+
ce->skb = skb;
pci_unmap_addr_set(ce, dma_addr, mapping);
pci_unmap_len_set(ce, dma_len, dma_len);
sge->stats.respQ_empty++;
if (cause & F_RESPQ_OVERFLOW) {
sge->stats.respQ_overflow++;
- CH_ALERT("%s: SGE response queue overflow\n",
+ pr_alert("%s: SGE response queue overflow\n",
adapter->name);
}
if (cause & F_FL_EXHAUSTED) {
}
if (cause & F_PACKET_TOO_BIG) {
sge->stats.pkt_too_big++;
- CH_ALERT("%s: SGE max packet size exceeded\n",
+ pr_alert("%s: SGE max packet size exceeded\n",
adapter->name);
}
if (cause & F_PACKET_MISMATCH) {
sge->stats.pkt_mismatch++;
- CH_ALERT("%s: SGE packet mismatch\n", adapter->name);
+ pr_alert("%s: SGE packet mismatch\n", adapter->name);
}
if (cause & SGE_INT_FATAL)
t1_fatal_err(adapter);
for_each_possible_cpu(cpu) {
struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[port], cpu);
- ss->rx_packets += st->rx_packets;
ss->rx_cso_good += st->rx_cso_good;
- ss->tx_packets += st->tx_packets;
ss->tx_cso += st->tx_cso;
ss->tx_tso += st->tx_tso;
+ ss->tx_need_hdrroom += st->tx_need_hdrroom;
ss->vlan_xtract += st->vlan_xtract;
ss->vlan_insert += st->vlan_insert;
}
}
}
+static int copybreak __read_mostly = 256;
+module_param(copybreak, int, 0);
+MODULE_PARM_DESC(copybreak, "Receive copy threshold");
+
/**
* get_packet - return the next ingress packet buffer
* @pdev: the PCI device that received the packet
* @fl: the SGE free list holding the packet
* @len: the actual packet length, excluding any SGE padding
- * @dma_pad: padding at beginning of buffer left by SGE DMA
- * @skb_pad: padding to be used if the packet is copied
- * @copy_thres: length threshold under which a packet should be copied
- * @drop_thres: # of remaining buffers before we start dropping packets
*
* Get the next packet from a free list and complete setup of the
* sk_buff. If the packet is small we make a copy and recycle the
* be copied but there is no memory for the copy.
*/
static inline struct sk_buff *get_packet(struct pci_dev *pdev,
- struct freelQ *fl, unsigned int len,
- int dma_pad, int skb_pad,
- unsigned int copy_thres,
- unsigned int drop_thres)
+ struct freelQ *fl, unsigned int len)
{
struct sk_buff *skb;
- struct freelQ_ce *ce = &fl->centries[fl->cidx];
+ const struct freelQ_ce *ce = &fl->centries[fl->cidx];
- if (len < copy_thres) {
- skb = alloc_skb(len + skb_pad, GFP_ATOMIC);
- if (likely(skb != NULL)) {
- skb_reserve(skb, skb_pad);
- skb_put(skb, len);
- pci_dma_sync_single_for_cpu(pdev,
- pci_unmap_addr(ce, dma_addr),
- pci_unmap_len(ce, dma_len),
- PCI_DMA_FROMDEVICE);
- memcpy(skb->data, ce->skb->data + dma_pad, len);
- pci_dma_sync_single_for_device(pdev,
+ if (len < copybreak) {
+ skb = alloc_skb(len + 2, GFP_ATOMIC);
+ if (!skb)
+ goto use_orig_buf;
+
+ skb_reserve(skb, 2); /* align IP header */
+ skb_put(skb, len);
+ pci_dma_sync_single_for_cpu(pdev,
pci_unmap_addr(ce, dma_addr),
pci_unmap_len(ce, dma_len),
PCI_DMA_FROMDEVICE);
- } else if (!drop_thres)
- goto use_orig_buf;
-
+ skb_copy_from_linear_data(ce->skb, skb->data, len);
+ pci_dma_sync_single_for_device(pdev,
+ pci_unmap_addr(ce, dma_addr),
+ pci_unmap_len(ce, dma_len),
+ PCI_DMA_FROMDEVICE);
recycle_fl_buf(fl, fl->cidx);
return skb;
}
- if (fl->credits < drop_thres) {
+use_orig_buf:
+ if (fl->credits < 2) {
recycle_fl_buf(fl, fl->cidx);
return NULL;
}
-use_orig_buf:
pci_unmap_single(pdev, pci_unmap_addr(ce, dma_addr),
pci_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE);
skb = ce->skb;
- skb_reserve(skb, dma_pad);
+ prefetch(skb->data);
+
skb_put(skb, len);
return skb;
}
pci_dma_sync_single_for_cpu(adapter->pdev, pci_unmap_addr(ce, dma_addr),
pci_unmap_len(ce, dma_len), PCI_DMA_FROMDEVICE);
- CH_ERR("%s: unexpected offload packet, cmd %u\n",
+ pr_err("%s: unexpected offload packet, cmd %u\n",
adapter->name, *skb->data);
recycle_fl_buf(fl, fl->cidx);
}
unsigned int len, unsigned int gen,
unsigned int eop)
{
- if (unlikely(len > SGE_TX_DESC_MAX_PLEN))
- BUG();
+ BUG_ON(len > SGE_TX_DESC_MAX_PLEN);
+
e->addr_lo = (u32)mapping;
e->addr_hi = (u64)mapping >> 32;
e->len_gen = V_CMD_LEN(len) | V_CMD_GEN1(gen);
*
* Process an ingress ethernet pakcet and deliver it to the stack.
*/
-static int sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
+static void sge_rx(struct sge *sge, struct freelQ *fl, unsigned int len)
{
struct sk_buff *skb;
- struct cpl_rx_pkt *p;
+ const struct cpl_rx_pkt *p;
struct adapter *adapter = sge->adapter;
struct sge_port_stats *st;
- skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad,
- sge->rx_pkt_pad, 2, SGE_RX_COPY_THRES,
- SGE_RX_DROP_THRES);
+ skb = get_packet(adapter->pdev, fl, len - sge->rx_pkt_pad);
if (unlikely(!skb)) {
sge->stats.rx_drops++;
- return 0;
+ return;
}
- p = (struct cpl_rx_pkt *)skb->data;
- skb_pull(skb, sizeof(*p));
+ p = (const struct cpl_rx_pkt *) skb->data;
if (p->iff >= adapter->params.nports) {
kfree_skb(skb);
- return 0;
+ return;
}
+ __skb_pull(skb, sizeof(*p));
- skb->dev = adapter->port[p->iff].dev;
- skb->dev->last_rx = jiffies;
- st = per_cpu_ptr(sge->port_stats[p->iff], smp_processor_id());
- st->rx_packets++;
+ st = this_cpu_ptr(sge->port_stats[p->iff]);
- skb->protocol = eth_type_trans(skb, skb->dev);
+ skb->protocol = eth_type_trans(skb, adapter->port[p->iff].dev);
if ((adapter->flags & RX_CSUM_ENABLED) && p->csum == 0xffff &&
skb->protocol == htons(ETH_P_IP) &&
(skb->data[9] == IPPROTO_TCP || skb->data[9] == IPPROTO_UDP)) {
if (unlikely(adapter->vlan_grp && p->vlan_valid)) {
st->vlan_xtract++;
-#ifdef CONFIG_CHELSIO_T1_NAPI
- vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
- ntohs(p->vlan));
-#else
- vlan_hwaccel_rx(skb, adapter->vlan_grp,
- ntohs(p->vlan));
-#endif
- } else {
-#ifdef CONFIG_CHELSIO_T1_NAPI
+ vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
+ ntohs(p->vlan));
+ } else
netif_receive_skb(skb);
-#else
- netif_rx(skb);
-#endif
- }
- return 0;
}
/*
static void restart_tx_queues(struct sge *sge)
{
struct adapter *adap = sge->adapter;
+ int i;
- if (enough_free_Tx_descs(&sge->cmdQ[0])) {
- int i;
+ if (!enough_free_Tx_descs(&sge->cmdQ[0]))
+ return;
- for_each_port(adap, i) {
- struct net_device *nd = adap->port[i].dev;
+ for_each_port(adap, i) {
+ struct net_device *nd = adap->port[i].dev;
- if (test_and_clear_bit(nd->if_port,
- &sge->stopped_tx_queues) &&
- netif_running(nd)) {
- sge->stats.cmdQ_restarted[2]++;
- netif_wake_queue(nd);
- }
+ if (test_and_clear_bit(nd->if_port, &sge->stopped_tx_queues) &&
+ netif_running(nd)) {
+ sge->stats.cmdQ_restarted[2]++;
+ netif_wake_queue(nd);
}
}
}
struct sge *sge = adapter->sge;
struct respQ *q = &sge->respQ;
struct respQ_e *e = &q->entries[q->cidx];
- int budget_left = budget;
+ int done = 0;
unsigned int flags = 0;
unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0};
-
- while (likely(budget_left && e->GenerationBit == q->genbit)) {
+ while (done < budget && e->GenerationBit == q->genbit) {
flags |= e->Qsleeping;
cmdq_processed[0] += e->Cmdq0CreditReturn;
* ping-pong of TX state information on MP where the sender
* might run on a different CPU than this function...
*/
- if (unlikely(flags & F_CMDQ0_ENABLE || cmdq_processed[0] > 64)) {
+ if (unlikely((flags & F_CMDQ0_ENABLE) || cmdq_processed[0] > 64)) {
flags = update_tx_info(adapter, flags, cmdq_processed[0]);
cmdq_processed[0] = 0;
}
+
if (unlikely(cmdq_processed[1] > 16)) {
sge->cmdQ[1].processed += cmdq_processed[1];
cmdq_processed[1] = 0;
}
+
if (likely(e->DataValid)) {
struct freelQ *fl = &sge->freelQ[e->FreelistQid];
else
sge_rx(sge, fl, e->BufferLength);
+ ++done;
+
/*
* Note: this depends on each packet consuming a
* single free-list buffer; cf. the BUG above.
*/
if (++fl->cidx == fl->size)
fl->cidx = 0;
+ prefetch(fl->centries[fl->cidx].skb);
+
if (unlikely(--fl->credits <
fl->size - SGE_FREEL_REFILL_THRESH))
refill_free_list(sge, fl);
writel(q->credits, adapter->regs + A_SG_RSPQUEUECREDIT);
q->credits = 0;
}
- --budget_left;
}
flags = update_tx_info(adapter, flags, cmdq_processed[0]);
sge->cmdQ[1].processed += cmdq_processed[1];
- budget -= budget_left;
- return budget;
+ return done;
+}
+
+static inline int responses_pending(const struct adapter *adapter)
+{
+ const struct respQ *Q = &adapter->sge->respQ;
+ const struct respQ_e *e = &Q->entries[Q->cidx];
+
+ return (e->GenerationBit == Q->genbit);
}
-#ifdef CONFIG_CHELSIO_T1_NAPI
/*
* A simpler version of process_responses() that handles only pure (i.e.,
* non data-carrying) responses. Such respones are too light-weight to justify
* which the caller must ensure is a valid pure response. Returns 1 if it
* encounters a valid data-carrying response, 0 otherwise.
*/
-static int process_pure_responses(struct adapter *adapter, struct respQ_e *e)
+static int process_pure_responses(struct adapter *adapter)
{
struct sge *sge = adapter->sge;
struct respQ *q = &sge->respQ;
+ struct respQ_e *e = &q->entries[q->cidx];
+ const struct freelQ *fl = &sge->freelQ[e->FreelistQid];
unsigned int flags = 0;
unsigned int cmdq_processed[SGE_CMDQ_N] = {0, 0};
+ prefetch(fl->centries[fl->cidx].skb);
+ if (e->DataValid)
+ return 1;
+
do {
flags |= e->Qsleeping;
* or protection from interrupts as data interrupts are off at this point and
* other adapter interrupts do not interfere.
*/
-int t1_poll(struct net_device *dev, int *budget)
+int t1_poll(struct napi_struct *napi, int budget)
{
- struct adapter *adapter = dev->priv;
- int effective_budget = min(*budget, dev->quota);
- int work_done = process_responses(adapter, effective_budget);
-
- *budget -= work_done;
- dev->quota -= work_done;
-
- if (work_done >= effective_budget)
- return 1;
-
- spin_lock_irq(&adapter->async_lock);
- __netif_rx_complete(dev);
- writel(adapter->sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
- writel(adapter->slow_intr_mask | F_PL_INTR_SGE_DATA,
- adapter->regs + A_PL_ENABLE);
- spin_unlock_irq(&adapter->async_lock);
+ struct adapter *adapter = container_of(napi, struct adapter, napi);
+ int work_done = process_responses(adapter, budget);
- return 0;
+ if (likely(work_done < budget)) {
+ napi_complete(napi);
+ writel(adapter->sge->respQ.cidx,
+ adapter->regs + A_SG_SLEEPING);
+ }
+ return work_done;
}
-/*
- * NAPI version of the main interrupt handler.
- */
irqreturn_t t1_interrupt(int irq, void *data)
{
struct adapter *adapter = data;
- struct net_device *dev = adapter->sge->netdev;
struct sge *sge = adapter->sge;
- u32 cause;
- int handled = 0;
-
- cause = readl(adapter->regs + A_PL_CAUSE);
- if (cause == 0 || cause == ~0)
- return IRQ_NONE;
-
- spin_lock(&adapter->async_lock);
- if (cause & F_PL_INTR_SGE_DATA) {
- struct respQ *q = &adapter->sge->respQ;
- struct respQ_e *e = &q->entries[q->cidx];
+ int handled;
- handled = 1;
+ if (likely(responses_pending(adapter))) {
writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
- if (e->GenerationBit == q->genbit &&
- __netif_rx_schedule_prep(dev)) {
- if (e->DataValid || process_pure_responses(adapter, e)) {
- /* mask off data IRQ */
- writel(adapter->slow_intr_mask,
- adapter->regs + A_PL_ENABLE);
- __netif_rx_schedule(sge->netdev);
- goto unlock;
+ if (napi_schedule_prep(&adapter->napi)) {
+ if (process_pure_responses(adapter))
+ __napi_schedule(&adapter->napi);
+ else {
+ /* no data, no NAPI needed */
+ writel(sge->respQ.cidx, adapter->regs + A_SG_SLEEPING);
+ /* undo schedule_prep */
+ napi_enable(&adapter->napi);
}
- /* no data, no NAPI needed */
- netif_poll_enable(dev);
-
}
- writel(q->cidx, adapter->regs + A_SG_SLEEPING);
- } else
- handled = t1_slow_intr_handler(adapter);
-
- if (!handled)
- sge->stats.unhandled_irqs++;
-unlock:
- spin_unlock(&adapter->async_lock);
- return IRQ_RETVAL(handled != 0);
-}
-
-#else
-/*
- * Main interrupt handler, optimized assuming that we took a 'DATA'
- * interrupt.
- *
- * 1. Clear the interrupt
- * 2. Loop while we find valid descriptors and process them; accumulate
- * information that can be processed after the loop
- * 3. Tell the SGE at which index we stopped processing descriptors
- * 4. Bookkeeping; free TX buffers, ring doorbell if there are any
- * outstanding TX buffers waiting, replenish RX buffers, potentially
- * reenable upper layers if they were turned off due to lack of TX
- * resources which are available again.
- * 5. If we took an interrupt, but no valid respQ descriptors was found we
- * let the slow_intr_handler run and do error handling.
- */
-irqreturn_t t1_interrupt(int irq, void *cookie)
-{
- int work_done;
- struct respQ_e *e;
- struct adapter *adapter = cookie;
- struct respQ *Q = &adapter->sge->respQ;
+ return IRQ_HANDLED;
+ }
spin_lock(&adapter->async_lock);
- e = &Q->entries[Q->cidx];
- prefetch(e);
-
- writel(F_PL_INTR_SGE_DATA, adapter->regs + A_PL_CAUSE);
-
- if (likely(e->GenerationBit == Q->genbit))
- work_done = process_responses(adapter, -1);
- else
- work_done = t1_slow_intr_handler(adapter);
+ handled = t1_slow_intr_handler(adapter);
+ spin_unlock(&adapter->async_lock);
- /*
- * The unconditional clearing of the PL_CAUSE above may have raced
- * with DMA completion and the corresponding generation of a response
- * to cause us to miss the resulting data interrupt. The next write
- * is also unconditional to recover the missed interrupt and render
- * this race harmless.
- */
- writel(Q->cidx, adapter->regs + A_SG_SLEEPING);
+ if (!handled)
+ sge->stats.unhandled_irqs++;
- if (!work_done)
- adapter->sge->stats.unhandled_irqs++;
- spin_unlock(&adapter->async_lock);
- return IRQ_RETVAL(work_done != 0);
+ return IRQ_RETVAL(handled != 0);
}
-#endif
/*
* Enqueues the sk_buff onto the cmdQ[qid] and has hardware fetch it.
netif_stop_queue(dev);
set_bit(dev->if_port, &sge->stopped_tx_queues);
sge->stats.cmdQ_full[2]++;
- CH_ERR("%s: Tx ring full while queue awake!\n",
+ pr_err("%s: Tx ring full while queue awake!\n",
adapter->name);
}
spin_unlock(&q->lock);
/*
* Adds the CPL header to the sk_buff and passes it to t1_sge_tx.
*/
-int t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
+netdev_tx_t t1_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct adapter *adapter = dev->priv;
+ struct adapter *adapter = dev->ml_priv;
struct sge *sge = adapter->sge;
- struct sge_port_stats *st = per_cpu_ptr(sge->port_stats[dev->if_port], smp_processor_id());
+ struct sge_port_stats *st = this_cpu_ptr(sge->port_stats[dev->if_port]);
struct cpl_tx_pkt *cpl;
struct sk_buff *orig_skb = skb;
int ret;
if (skb->protocol == htons(ETH_P_CPL5))
goto send;
+ /*
+ * We are using a non-standard hard_header_len.
+ * Allocate more header room in the rare cases it is not big enough.
+ */
+ if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) {
+ skb = skb_realloc_headroom(skb, sizeof(struct cpl_tx_pkt_lso));
+ ++st->tx_need_hdrroom;
+ dev_kfree_skb_any(orig_skb);
+ if (!skb)
+ return NETDEV_TX_OK;
+ }
+
if (skb_shinfo(skb)->gso_size) {
int eth_type;
struct cpl_tx_pkt_lso *hdr;
++st->tx_tso;
- eth_type = skb->nh.raw - skb->data == ETH_HLEN ?
+ eth_type = skb_network_offset(skb) == ETH_HLEN ?
CPL_ETH_II : CPL_ETH_II_VLAN;
hdr = (struct cpl_tx_pkt_lso *)skb_push(skb, sizeof(*hdr));
hdr->opcode = CPL_TX_PKT_LSO;
hdr->ip_csum_dis = hdr->l4_csum_dis = 0;
- hdr->ip_hdr_words = skb->nh.iph->ihl;
- hdr->tcp_hdr_words = skb->h.th->doff;
+ hdr->ip_hdr_words = ip_hdr(skb)->ihl;
+ hdr->tcp_hdr_words = tcp_hdr(skb)->doff;
hdr->eth_type_mss = htons(MK_ETH_TYPE_MSS(eth_type,
skb_shinfo(skb)->gso_size));
hdr->len = htonl(skb->len - sizeof(*hdr));
return NETDEV_TX_OK;
}
- /*
- * We are using a non-standard hard_header_len and some kernel
- * components, such as pktgen, do not handle it right.
- * Complain when this happens but try to fix things up.
- */
- if (unlikely(skb_headroom(skb) < dev->hard_header_len - ETH_HLEN)) {
- pr_debug("%s: headroom %d header_len %d\n", dev->name,
- skb_headroom(skb), dev->hard_header_len);
-
- if (net_ratelimit())
- printk(KERN_ERR "%s: inadequate headroom in "
- "Tx packet\n", dev->name);
- skb = skb_realloc_headroom(skb, sizeof(*cpl));
- dev_kfree_skb_any(orig_skb);
- if (!skb)
- return NETDEV_TX_OK;
- }
-
if (!(adapter->flags & UDP_CSUM_CAPABLE) &&
skb->ip_summed == CHECKSUM_PARTIAL &&
- skb->nh.iph->protocol == IPPROTO_UDP) {
+ ip_hdr(skb)->protocol == IPPROTO_UDP) {
if (unlikely(skb_checksum_help(skb))) {
pr_debug("%s: unable to do udp checksum\n", dev->name);
dev_kfree_skb_any(skb);
*/
if ((unlikely(!adapter->sge->espibug_skb[dev->if_port]))) {
if (skb->protocol == htons(ETH_P_ARP) &&
- skb->nh.arph->ar_op == htons(ARPOP_REQUEST)) {
+ arp_hdr(skb)->ar_op == htons(ARPOP_REQUEST)) {
adapter->sge->espibug_skb[dev->if_port] = skb;
/* We want to re-use this skb later. We
* simply bump the reference count and it
cpl->vlan_valid = 0;
send:
- st->tx_packets++;
- dev->trans_start = jiffies;
ret = t1_sge_tx(skb, adapter, 0, dev);
/* If transmit busy, and we reallocated skb's due to headroom limit,
tx_sched_stop(sge);
for (i = 0; i < MAX_NPORTS; i++)
- if (sge->espibug_skb[i])
- kfree_skb(sge->espibug_skb[i]);
+ kfree_skb(sge->espibug_skb[i]);
}
/*
0x0, 0x7, 0x43, 0x0, 0x0, 0x0
};
- memcpy(skb->data + sizeof(struct cpl_tx_pkt),
- ch_mac_addr, ETH_ALEN);
- memcpy(skb->data + skb->len - 10,
- ch_mac_addr, ETH_ALEN);
+ skb_copy_to_linear_data_offset(skb,
+ sizeof(struct cpl_tx_pkt),
+ ch_mac_addr,
+ ETH_ALEN);
+ skb_copy_to_linear_data_offset(skb,
+ skb->len - 10,
+ ch_mac_addr,
+ ETH_ALEN);
skb->cb[0] = 0xff;
}
if (!skb->cb[0]) {
u8 ch_mac_addr[ETH_ALEN] =
{0x0, 0x7, 0x43, 0x0, 0x0, 0x0};
- memcpy(skb->data + sizeof(struct cpl_tx_pkt),
- ch_mac_addr, ETH_ALEN);
- memcpy(skb->data + skb->len - 10, ch_mac_addr,
- ETH_ALEN);
+ skb_copy_to_linear_data_offset(skb,
+ sizeof(struct cpl_tx_pkt),
+ ch_mac_addr,
+ ETH_ALEN);
+ skb_copy_to_linear_data_offset(skb,
+ skb->len - 10,
+ ch_mac_addr,
+ ETH_ALEN);
skb->cb[0] = 0xff;
}