static const struct ethtool_ops ql3xxx_ethtool_ops = {
.get_settings = ql_get_settings,
.get_drvinfo = ql_get_drvinfo,
- .get_perm_addr = ethtool_op_get_perm_addr,
.get_link = ethtool_op_get_link,
.get_msglevel = ql_get_msglevel,
.set_msglevel = ql_set_msglevel,
qdev->rsp_consumer_index) && (work_done < work_to_do)) {
net_rsp = qdev->rsp_current;
+ rmb();
+ /*
+ * Fix 4032 chipe undocumented "feature" where bit-8 is set if the
+ * inbound completion is for a VLAN.
+ */
+ if (qdev->device_id == QL3032_DEVICE_ID)
+ net_rsp->opcode &= 0x7f;
switch (net_rsp->opcode) {
case OPCODE_OB_MAC_IOCB_FN0:
return work_done;
}
-static int ql_poll(struct net_device *ndev, int *budget)
+static int ql_poll(struct napi_struct *napi, int budget)
{
- struct ql3_adapter *qdev = netdev_priv(ndev);
- int work_to_do = min(*budget, ndev->quota);
+ struct ql3_adapter *qdev = container_of(napi, struct ql3_adapter, napi);
+ struct net_device *ndev = qdev->ndev;
int rx_cleaned = 0, tx_cleaned = 0;
unsigned long hw_flags;
struct ql3xxx_port_registers __iomem *port_regs = qdev->mem_map_registers;
if (!netif_carrier_ok(ndev))
goto quit_polling;
- ql_tx_rx_clean(qdev, &tx_cleaned, &rx_cleaned, work_to_do);
- *budget -= rx_cleaned;
- ndev->quota -= rx_cleaned;
+ ql_tx_rx_clean(qdev, &tx_cleaned, &rx_cleaned, budget);
- if( tx_cleaned + rx_cleaned != work_to_do ||
+ if (tx_cleaned + rx_cleaned != budget ||
!netif_running(ndev)) {
quit_polling:
- netif_rx_complete(ndev);
-
spin_lock_irqsave(&qdev->hw_lock, hw_flags);
+ __netif_rx_complete(ndev, napi);
ql_update_small_bufq_prod_index(qdev);
ql_update_lrg_bufq_prod_index(qdev);
writel(qdev->rsp_consumer_index,
spin_unlock_irqrestore(&qdev->hw_lock, hw_flags);
ql_enable_interrupts(qdev);
- return 0;
}
- return 1;
+ return tx_cleaned + rx_cleaned;
}
static irqreturn_t ql3xxx_isr(int irq, void *dev_id)
spin_unlock(&qdev->adapter_lock);
} else if (value & ISP_IMR_DISABLE_CMPL_INT) {
ql_disable_interrupts(qdev);
- if (likely(netif_rx_schedule_prep(ndev))) {
- __netif_rx_schedule(ndev);
+ if (likely(netif_rx_schedule_prep(ndev, &qdev->napi))) {
+ __netif_rx_schedule(ndev, &qdev->napi);
}
} else {
return IRQ_NONE;
return -1;
}
-static void ql_hw_csum_setup(struct sk_buff *skb,
+static void ql_hw_csum_setup(const struct sk_buff *skb,
struct ob_mac_iocb_req *mac_iocb_ptr)
{
- struct ethhdr *eth;
- struct iphdr *ip = NULL;
- u8 offset = ETH_HLEN;
+ const struct iphdr *ip = ip_hdr(skb);
- eth = (struct ethhdr *)(skb->data);
+ mac_iocb_ptr->ip_hdr_off = skb_network_offset(skb);
+ mac_iocb_ptr->ip_hdr_len = ip->ihl;
- if (eth->h_proto == __constant_htons(ETH_P_IP)) {
- ip = (struct iphdr *)&skb->data[ETH_HLEN];
- } else if (eth->h_proto == htons(ETH_P_8021Q) &&
- ((struct vlan_ethhdr *)skb->data)->
- h_vlan_encapsulated_proto == __constant_htons(ETH_P_IP)) {
- ip = (struct iphdr *)&skb->data[VLAN_ETH_HLEN];
- offset = VLAN_ETH_HLEN;
- }
-
- if (ip) {
- if (ip->protocol == IPPROTO_TCP) {
- mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
+ if (ip->protocol == IPPROTO_TCP) {
+ mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_TC |
OB_3032MAC_IOCB_REQ_IC;
- mac_iocb_ptr->ip_hdr_off = offset;
- mac_iocb_ptr->ip_hdr_len = ip->ihl;
- } else if (ip->protocol == IPPROTO_UDP) {
- mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
+ } else {
+ mac_iocb_ptr->flags1 |= OB_3032MAC_IOCB_REQ_UC |
OB_3032MAC_IOCB_REQ_IC;
- mac_iocb_ptr->ip_hdr_off = offset;
- mac_iocb_ptr->ip_hdr_len = ip->ihl;
- }
}
+
}
/*
del_timer_sync(&qdev->adapter_timer);
- netif_poll_disable(ndev);
+ napi_disable(&qdev->napi);
if (do_reset) {
int soft_reset;
mod_timer(&qdev->adapter_timer, jiffies + HZ * 1);
- netif_poll_enable(ndev);
+ napi_enable(&qdev->napi);
ql_enable_interrupts(qdev);
return 0;
ndev->tx_timeout = ql3xxx_tx_timeout;
ndev->watchdog_timeo = 5 * HZ;
- ndev->poll = &ql_poll;
- ndev->weight = 64;
+ netif_napi_add(ndev, &qdev->napi, ql_poll, 64);
ndev->irq = pdev->irq;