diff options
Diffstat (limited to 'drivers')
29 files changed, 397 insertions, 161 deletions
diff --git a/drivers/net/arm/am79c961a.c b/drivers/net/arm/am79c961a.c index 7b3e23f38913..52fe21e1e2cd 100644 --- a/drivers/net/arm/am79c961a.c +++ b/drivers/net/arm/am79c961a.c @@ -199,17 +199,15 @@ am79c961_ramtest(struct net_device *dev, unsigned int val) static void am79c961_mc_hash(char *addr, u16 *hash) { - if (addr[0] & 0x01) { - int idx, bit; - u32 crc; + int idx, bit; + u32 crc; - crc = ether_crc_le(ETH_ALEN, addr); + crc = ether_crc_le(ETH_ALEN, addr); - idx = crc >> 30; - bit = (crc >> 26) & 15; + idx = crc >> 30; + bit = (crc >> 26) & 15; - hash[idx] |= 1 << bit; - } + hash[idx] |= 1 << bit; } static unsigned int am79c961_get_rx_mode(struct net_device *dev, u16 *hash) diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 30719f591fb2..f520a5c75032 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -106,14 +106,24 @@ static int be_mcc_compl_process(struct be_adapter *adapter, netdev_stats_update(adapter); adapter->stats_cmd_sent = false; } - } else if ((compl_status != MCC_STATUS_NOT_SUPPORTED) && - (compl->tag0 != OPCODE_COMMON_NTWK_MAC_QUERY)) { - extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & - CQE_STATUS_EXTD_MASK; - dev_warn(&adapter->pdev->dev, - "Error in cmd completion - opcode %d, compl %d, extd %d\n", - compl->tag0, compl_status, extd_status); + } else { + if (compl_status == MCC_STATUS_NOT_SUPPORTED || + compl_status == MCC_STATUS_ILLEGAL_REQUEST) + goto done; + + if (compl_status == MCC_STATUS_UNAUTHORIZED_REQUEST) { + dev_warn(&adapter->pdev->dev, "This domain(VM) is not " + "permitted to execute this cmd (opcode %d)\n", + compl->tag0); + } else { + extd_status = (compl->status >> CQE_STATUS_EXTD_SHIFT) & + CQE_STATUS_EXTD_MASK; + dev_err(&adapter->pdev->dev, "Cmd (opcode %d) failed:" + "status %d, extd-status %d\n", + compl->tag0, compl_status, extd_status); + } } +done: return compl_status; } @@ -974,7 +984,7 @@ int be_cmd_txq_create(struct be_adapter *adapter, return status; } -/* Uses mbox */ +/* Uses MCC */ int be_cmd_rxq_create(struct be_adapter *adapter, struct be_queue_info *rxq, u16 cq_id, u16 frag_size, u16 max_frame_size, u32 if_id, u32 rss, u8 *rss_id) @@ -984,10 +994,13 @@ int be_cmd_rxq_create(struct be_adapter *adapter, struct be_dma_mem *q_mem = &rxq->dma_mem; int status; - if (mutex_lock_interruptible(&adapter->mbox_lock)) - return -1; + spin_lock_bh(&adapter->mcc_lock); - wrb = wrb_from_mbox(adapter); + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } req = embedded_payload(wrb); be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, @@ -1004,7 +1017,7 @@ int be_cmd_rxq_create(struct be_adapter *adapter, req->max_frame_size = cpu_to_le16(max_frame_size); req->rss_queue = cpu_to_le32(rss); - status = be_mbox_notify_wait(adapter); + status = be_mcc_notify_wait(adapter); if (!status) { struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); rxq->id = le16_to_cpu(resp->id); @@ -1012,8 +1025,8 @@ int be_cmd_rxq_create(struct be_adapter *adapter, *rss_id = resp->rss_id; } - mutex_unlock(&adapter->mbox_lock); - +err: + spin_unlock_bh(&adapter->mcc_lock); return status; } @@ -1068,9 +1081,40 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, req->id = cpu_to_le16(q->id); status = be_mbox_notify_wait(adapter); + if (!status) + q->created = false; mutex_unlock(&adapter->mbox_lock); + return status; +} +/* Uses MCC */ +int be_cmd_rxq_destroy(struct be_adapter *adapter, struct be_queue_info *q) +{ + struct be_mcc_wrb *wrb; + struct be_cmd_req_q_destroy *req; + int status; + + spin_lock_bh(&adapter->mcc_lock); + + wrb = wrb_from_mccq(adapter); + if (!wrb) { + status = -EBUSY; + goto err; + } + req = embedded_payload(wrb); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0, OPCODE_ETH_RX_DESTROY); + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_DESTROY, + sizeof(*req)); + req->id = cpu_to_le16(q->id); + + status = be_mcc_notify_wait(adapter); + if (!status) + q->created = false; + +err: + spin_unlock_bh(&adapter->mcc_lock); return status; } diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h index d08289e21f61..1151df6b0020 100644 --- a/drivers/net/benet/be_cmds.h +++ b/drivers/net/benet/be_cmds.h @@ -51,17 +51,12 @@ struct be_mcc_wrb { /* Completion Status */ enum { - MCC_STATUS_SUCCESS = 0x0, -/* The client does not have sufficient privileges to execute the command */ - MCC_STATUS_INSUFFICIENT_PRIVILEGES = 0x1, -/* A parameter in the command was invalid. */ - MCC_STATUS_INVALID_PARAMETER = 0x2, -/* There are insufficient chip resources to execute the command */ - MCC_STATUS_INSUFFICIENT_RESOURCES = 0x3, -/* The command is completing because the queue was getting flushed */ - MCC_STATUS_QUEUE_FLUSHING = 0x4, -/* The command is completing with a DMA error */ - MCC_STATUS_DMA_FAILED = 0x5, + MCC_STATUS_SUCCESS = 0, + MCC_STATUS_FAILED = 1, + MCC_STATUS_ILLEGAL_REQUEST = 2, + MCC_STATUS_ILLEGAL_FIELD = 3, + MCC_STATUS_INSUFFICIENT_BUFFER = 4, + MCC_STATUS_UNAUTHORIZED_REQUEST = 5, MCC_STATUS_NOT_SUPPORTED = 66 }; @@ -1487,6 +1482,8 @@ extern int be_cmd_rxq_create(struct be_adapter *adapter, u32 rss, u8 *rss_id); extern int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q, int type); +extern int be_cmd_rxq_destroy(struct be_adapter *adapter, + struct be_queue_info *q); extern int be_cmd_link_status_query(struct be_adapter *adapter, bool *link_up, u8 *mac_speed, u16 *link_speed, u32 dom); extern int be_cmd_reset(struct be_adapter *adapter); diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index ae281de94b99..696f634b7e38 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1572,6 +1572,7 @@ static void be_rx_q_clean(struct be_adapter *adapter, struct be_rx_obj *rxo) memset(page_info, 0, sizeof(*page_info)); } BUG_ON(atomic_read(&rxq->used)); + rxq->tail = rxq->head = 0; } static void be_tx_compl_clean(struct be_adapter *adapter, @@ -1752,29 +1753,16 @@ static void be_rx_queues_destroy(struct be_adapter *adapter) int i; for_all_rx_queues(adapter, rxo, i) { - q = &rxo->q; - if (q->created) { - be_cmd_q_destroy(adapter, q, QTYPE_RXQ); - /* After the rxq is invalidated, wait for a grace time - * of 1ms for all dma to end and the flush compl to - * arrive - */ - mdelay(1); - be_rx_q_clean(adapter, rxo); - } - be_queue_free(adapter, q); + be_queue_free(adapter, &rxo->q); q = &rxo->cq; if (q->created) be_cmd_q_destroy(adapter, q, QTYPE_CQ); be_queue_free(adapter, q); - /* Clear any residual events */ q = &rxo->rx_eq.q; - if (q->created) { - be_eq_clean(adapter, &rxo->rx_eq); + if (q->created) be_cmd_q_destroy(adapter, q, QTYPE_EQ); - } be_queue_free(adapter, q); } } @@ -1833,30 +1821,14 @@ static int be_rx_queues_create(struct be_adapter *adapter) rc = be_cmd_cq_create(adapter, cq, eq, false, false, 3); if (rc) goto err; - /* Rx Q */ + + /* Rx Q - will be created in be_open() */ q = &rxo->q; rc = be_queue_alloc(adapter, q, RX_Q_LEN, sizeof(struct be_eth_rx_d)); if (rc) goto err; - rc = be_cmd_rxq_create(adapter, q, cq->id, rx_frag_size, - BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, - (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id); - if (rc) - goto err; - } - - if (be_multi_rxq(adapter)) { - u8 rsstable[MAX_RSS_QS]; - - for_all_rss_queues(adapter, rxo, i) - rsstable[i] = rxo->rss_id; - - rc = be_cmd_rss_config(adapter, rsstable, - adapter->num_rx_qs - 1); - if (rc) - goto err; } return 0; @@ -2302,6 +2274,31 @@ done: adapter->isr_registered = false; } +static void be_rx_queues_clear(struct be_adapter *adapter) +{ + struct be_queue_info *q; + struct be_rx_obj *rxo; + int i; + + for_all_rx_queues(adapter, rxo, i) { + q = &rxo->q; + if (q->created) { + be_cmd_rxq_destroy(adapter, q); + /* After the rxq is invalidated, wait for a grace time + * of 1ms for all dma to end and the flush compl to + * arrive + */ + mdelay(1); + be_rx_q_clean(adapter, rxo); + } + + /* Clear any residual events */ + q = &rxo->rx_eq.q; + if (q->created) + be_eq_clean(adapter, &rxo->rx_eq); + } +} + static int be_close(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); @@ -2350,6 +2347,40 @@ static int be_close(struct net_device *netdev) for_all_tx_queues(adapter, txo, i) be_tx_compl_clean(adapter, txo); + be_rx_queues_clear(adapter); + return 0; +} + +static int be_rx_queues_setup(struct be_adapter *adapter) +{ + struct be_rx_obj *rxo; + int rc, i; + u8 rsstable[MAX_RSS_QS]; + + for_all_rx_queues(adapter, rxo, i) { + rc = be_cmd_rxq_create(adapter, &rxo->q, rxo->cq.id, + rx_frag_size, BE_MAX_JUMBO_FRAME_SIZE, + adapter->if_handle, + (i > 0) ? 1 : 0/* rss enable */, &rxo->rss_id); + if (rc) + return rc; + } + + if (be_multi_rxq(adapter)) { + for_all_rss_queues(adapter, rxo, i) + rsstable[i] = rxo->rss_id; + + rc = be_cmd_rss_config(adapter, rsstable, + adapter->num_rx_qs - 1); + if (rc) + return rc; + } + + /* First time posting */ + for_all_rx_queues(adapter, rxo, i) { + be_post_rx_frags(rxo, GFP_KERNEL); + napi_enable(&rxo->rx_eq.napi); + } return 0; } @@ -2363,10 +2394,10 @@ static int be_open(struct net_device *netdev) u8 mac_speed; u16 link_speed; - for_all_rx_queues(adapter, rxo, i) { - be_post_rx_frags(rxo, GFP_KERNEL); - napi_enable(&rxo->rx_eq.napi); - } + status = be_rx_queues_setup(adapter); + if (status) + goto err; + napi_enable(&tx_eq->napi); be_irq_register(adapter); @@ -3386,6 +3417,12 @@ static int __devinit be_probe(struct pci_dev *pdev, if (status) goto stats_clean; + /* The INTR bit may be set in the card when probed by a kdump kernel + * after a crash. + */ + if (!lancer_chip(adapter)) + be_intr_set(adapter, false); + be_msix_enable(adapter); INIT_DELAYED_WORK(&adapter->work, be_worker); diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index bbf06f77ee8c..906366b54037 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -4,7 +4,6 @@ menu "CAN Device Drivers" config CAN_VCAN tristate "Virtual Local CAN Interface (vcan)" depends on CAN - default N ---help--- Similar to the network loopback devices, vcan offers a virtual local CAN interface. @@ -15,7 +14,6 @@ config CAN_VCAN config CAN_SLCAN tristate "Serial / USB serial CAN Adaptors (slcan)" depends on CAN - default N ---help--- CAN driver for several 'low cost' CAN interfaces that are attached via serial lines or via USB-to-serial adapters using the LAWICEL @@ -125,7 +123,6 @@ source "drivers/net/can/softing/Kconfig" config CAN_DEBUG_DEVICES bool "CAN devices debugging messages" depends on CAN - default N ---help--- Say Y here if you want the CAN device drivers to produce a bunch of debug messages to the system log. Select this if you are having diff --git a/drivers/net/depca.c b/drivers/net/depca.c index d54a0e93ba93..a7ccaa67c7d4 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -1270,7 +1270,6 @@ static void SetMulticastFilter(struct net_device *dev) { struct depca_private *lp = netdev_priv(dev); struct netdev_hw_addr *ha; - char *addrs; int i, j, bit, byte; u16 hashcode; u32 crc; @@ -1285,19 +1284,15 @@ static void SetMulticastFilter(struct net_device *dev) } /* Add multicast addresses */ netdev_for_each_mc_addr(ha, dev) { - addrs = ha->addr; - if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = ether_crc(ETH_ALEN, addrs); - hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ - for (j = 0; j < 5; j++) { /* ... in reverse order. */ - hashcode = (hashcode << 1) | ((crc >>= 1) & 1); - } - - - byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ - bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ - lp->init_block.mcast_table[byte] |= bit; + crc = ether_crc(ETH_ALEN, ha->addr); + hashcode = (crc & 1); /* hashcode is 6 LSb of CRC ... */ + for (j = 0; j < 5; j++) { /* ... in reverse order. */ + hashcode = (hashcode << 1) | ((crc >>= 1) & 1); } + + byte = hashcode >> 3; /* bit[3-5] -> byte in filter */ + bit = 1 << (hashcode & 0x07); /* bit[0-2] -> bit in byte */ + lp->init_block.mcast_table[byte] |= bit; } } } diff --git a/drivers/net/enic/enic.h b/drivers/net/enic/enic.h index f747bceb75b1..f0b062b4a223 100644 --- a/drivers/net/enic/enic.h +++ b/drivers/net/enic/enic.h @@ -32,7 +32,7 @@ #define DRV_NAME "enic" #define DRV_DESCRIPTION "Cisco VIC Ethernet NIC Driver" -#define DRV_VERSION "2.1.1.20" +#define DRV_VERSION "2.1.1.24" #define DRV_COPYRIGHT "Copyright 2008-2011 Cisco Systems, Inc" #define ENIC_BARS_MAX 6 diff --git a/drivers/net/enic/enic_dev.c b/drivers/net/enic/enic_dev.c index 90687b14e60f..fd6247b3c0ee 100644 --- a/drivers/net/enic/enic_dev.c +++ b/drivers/net/enic/enic_dev.c @@ -166,6 +166,17 @@ int enic_dev_disable(struct enic *enic) return err; } +int enic_dev_intr_coal_timer_info(struct enic *enic) +{ + int err; + + spin_lock(&enic->devcmd_lock); + err = vnic_dev_intr_coal_timer_info(enic->vdev); + spin_unlock(&enic->devcmd_lock); + + return err; +} + int enic_vnic_dev_deinit(struct enic *enic) { int err; diff --git a/drivers/net/enic/enic_dev.h b/drivers/net/enic/enic_dev.h index d5f681337626..ff8e87fdfc1d 100644 --- a/drivers/net/enic/enic_dev.h +++ b/drivers/net/enic/enic_dev.h @@ -34,6 +34,7 @@ int enic_dev_hang_notify(struct enic *enic); int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic); int enic_dev_enable(struct enic *enic); int enic_dev_disable(struct enic *enic); +int enic_dev_intr_coal_timer_info(struct enic *enic); int enic_vnic_dev_deinit(struct enic *enic); int enic_dev_init_prov2(struct enic *enic, struct vic_provinfo *vp); int enic_dev_deinit_done(struct enic *enic, int *status); diff --git a/drivers/net/enic/enic_main.c b/drivers/net/enic/enic_main.c index 4b3a93a924e8..e25800fa96ca 100644 --- a/drivers/net/enic/enic_main.c +++ b/drivers/net/enic/enic_main.c @@ -284,12 +284,10 @@ static int enic_set_coalesce(struct net_device *netdev, u32 rx_coalesce_usecs; unsigned int i, intr; - tx_coalesce_usecs = min_t(u32, - INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), - ecmd->tx_coalesce_usecs); - rx_coalesce_usecs = min_t(u32, - INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), - ecmd->rx_coalesce_usecs); + tx_coalesce_usecs = min_t(u32, ecmd->tx_coalesce_usecs, + vnic_dev_get_intr_coal_timer_max(enic->vdev)); + rx_coalesce_usecs = min_t(u32, ecmd->rx_coalesce_usecs, + vnic_dev_get_intr_coal_timer_max(enic->vdev)); switch (vnic_dev_get_intr_mode(enic->vdev)) { case VNIC_DEV_INTR_MODE_INTX: @@ -298,26 +296,26 @@ static int enic_set_coalesce(struct net_device *netdev, intr = enic_legacy_io_intr(); vnic_intr_coalescing_timer_set(&enic->intr[intr], - INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); + tx_coalesce_usecs); break; case VNIC_DEV_INTR_MODE_MSI: if (tx_coalesce_usecs != rx_coalesce_usecs) return -EINVAL; vnic_intr_coalescing_timer_set(&enic->intr[0], - INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); + tx_coalesce_usecs); break; case VNIC_DEV_INTR_MODE_MSIX: for (i = 0; i < enic->wq_count; i++) { intr = enic_msix_wq_intr(enic, i); vnic_intr_coalescing_timer_set(&enic->intr[intr], - INTR_COALESCE_USEC_TO_HW(tx_coalesce_usecs)); + tx_coalesce_usecs); } for (i = 0; i < enic->rq_count; i++) { intr = enic_msix_rq_intr(enic, i); vnic_intr_coalescing_timer_set(&enic->intr[intr], - INTR_COALESCE_USEC_TO_HW(rx_coalesce_usecs)); + rx_coalesce_usecs); } break; @@ -2175,6 +2173,14 @@ static int enic_dev_init(struct enic *enic) unsigned int i; int err; + /* Get interrupt coalesce timer info */ + err = enic_dev_intr_coal_timer_info(enic); + if (err) { + dev_warn(dev, "Using default conversion factor for " + "interrupt coalesce timer\n"); + vnic_dev_intr_coal_timer_info_default(enic->vdev); + } + /* Get vNIC configuration */ diff --git a/drivers/net/enic/enic_res.c b/drivers/net/enic/enic_res.c index 34f42072b60c..4a35367de790 100644 --- a/drivers/net/enic/enic_res.c +++ b/drivers/net/enic/enic_res.c @@ -90,9 +90,8 @@ int enic_get_vnic_config(struct enic *enic) max_t(u16, ENIC_MIN_MTU, c->mtu)); - c->intr_timer_usec = min_t(u32, - INTR_COALESCE_HW_TO_USEC(VNIC_INTR_TIMER_MAX), - c->intr_timer_usec); + c->intr_timer_usec = min_t(u32, c->intr_timer_usec, + vnic_dev_get_intr_coal_timer_max(enic->vdev)); dev_info(enic_get_dev(enic), "vNIC MAC addr %pM wq/rq %d/%d mtu %d\n", @@ -303,7 +302,7 @@ void enic_init_vnic_resources(struct enic *enic) for (i = 0; i < enic->intr_count; i++) { vnic_intr_init(&enic->intr[i], - INTR_COALESCE_USEC_TO_HW(enic->config.intr_timer_usec), + enic->config.intr_timer_usec, enic->config.intr_timer_type, mask_on_assertion); } diff --git a/drivers/net/enic/vnic_dev.c b/drivers/net/enic/vnic_dev.c index 68f24ae860ae..8c4c8cf486f6 100644 --- a/drivers/net/enic/vnic_dev.c +++ b/drivers/net/enic/vnic_dev.c @@ -40,6 +40,12 @@ struct vnic_res { unsigned int count; }; +struct vnic_intr_coal_timer_info { + u32 mul; + u32 div; + u32 max_usec; +}; + struct vnic_dev { void *priv; struct pci_dev *pdev; @@ -58,6 +64,7 @@ struct vnic_dev { enum vnic_proxy_type proxy; u32 proxy_index; u64 args[VNIC_DEVCMD_NARGS]; + struct vnic_intr_coal_timer_info intr_coal_timer_info; }; #define VNIC_MAX_RES_HDR_SIZE \ @@ -794,6 +801,42 @@ int vnic_dev_deinit(struct vnic_dev *vdev) return vnic_dev_cmd(vdev, CMD_DEINIT, &a0, &a1, wait); } +void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev) +{ + /* Default: hardware intr coal timer is in units of 1.5 usecs */ + vdev->intr_coal_timer_info.mul = 2; + vdev->intr_coal_timer_info.div = 3; + vdev->intr_coal_timer_info.max_usec = + vnic_dev_intr_coal_timer_hw_to_usec(vdev, 0xffff); +} + +int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev) +{ + int wait = 1000; + int err; + + memset(vdev->args, 0, sizeof(vdev->args)); + + err = _vnic_dev_cmd(vdev, CMD_INTR_COAL_CONVERT, wait); + + /* Use defaults when firmware doesn't support the devcmd at all or + * supports it for only specific hardware + */ + if ((err == ERR_ECMDUNKNOWN) || + (!err && !(vdev->args[0] && vdev->args[1] && vdev->args[2]))) { + pr_warning("Using default conversion factor for " + "interrupt coalesce timer\n"); + vnic_dev_intr_coal_timer_info_default(vdev); + return 0; + } + + vdev->intr_coal_timer_info.mul = (u32) vdev->args[0]; + vdev->intr_coal_timer_info.div = (u32) vdev->args[1]; + vdev->intr_coal_timer_info.max_usec = (u32) vdev->args[2]; + + return err; +} + int vnic_dev_link_status(struct vnic_dev *vdev) { if (!vnic_dev_notify_ready(vdev)) @@ -838,6 +881,23 @@ enum vnic_dev_intr_mode vnic_dev_get_intr_mode( return vdev->intr_mode; } +u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec) +{ + return (usec * vdev->intr_coal_timer_info.mul) / + vdev->intr_coal_timer_info.div; +} + +u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles) +{ + return (hw_cycles * vdev->intr_coal_timer_info.div) / + vdev->intr_coal_timer_info.mul; +} + +u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev) +{ + return vdev->intr_coal_timer_info.max_usec; +} + void vnic_dev_unregister(struct vnic_dev *vdev) { if (vdev) { diff --git a/drivers/net/enic/vnic_dev.h b/drivers/net/enic/vnic_dev.h index cf482a2c9dd9..852b698fbe7d 100644 --- a/drivers/net/enic/vnic_dev.h +++ b/drivers/net/enic/vnic_dev.h @@ -109,11 +109,16 @@ int vnic_dev_open(struct vnic_dev *vdev, int arg); int vnic_dev_open_done(struct vnic_dev *vdev, int *done); int vnic_dev_init(struct vnic_dev *vdev, int arg); int vnic_dev_deinit(struct vnic_dev *vdev); +void vnic_dev_intr_coal_timer_info_default(struct vnic_dev *vdev); +int vnic_dev_intr_coal_timer_info(struct vnic_dev *vdev); int vnic_dev_hang_reset(struct vnic_dev *vdev, int arg); int vnic_dev_hang_reset_done(struct vnic_dev *vdev, int *done); void vnic_dev_set_intr_mode(struct vnic_dev *vdev, enum vnic_dev_intr_mode intr_mode); enum vnic_dev_intr_mode vnic_dev_get_intr_mode(struct vnic_dev *vdev); +u32 vnic_dev_intr_coal_timer_usec_to_hw(struct vnic_dev *vdev, u32 usec); +u32 vnic_dev_intr_coal_timer_hw_to_usec(struct vnic_dev *vdev, u32 hw_cycles); +u32 vnic_dev_get_intr_coal_timer_max(struct vnic_dev *vdev); void vnic_dev_unregister(struct vnic_dev *vdev); int vnic_dev_set_ig_vlan_rewrite_mode(struct vnic_dev *vdev, u8 ig_vlan_rewrite_mode); diff --git a/drivers/net/enic/vnic_devcmd.h b/drivers/net/enic/vnic_devcmd.h index c5569bfb47ac..8025e8808d61 100644 --- a/drivers/net/enic/vnic_devcmd.h +++ b/drivers/net/enic/vnic_devcmd.h @@ -318,6 +318,25 @@ enum vnic_devcmd_cmd { * ERR_EINPROGRESS - command in a0 is still in progress */ CMD_STATUS = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 49), + + /* + * Returns interrupt coalescing timer conversion factors. + * After calling this devcmd, ENIC driver can convert + * interrupt coalescing timer in usec into CPU cycles as follows: + * + * intr_timer_cycles = intr_timer_usec * multiplier / divisor + * + * Interrupt coalescing timer in usecs can be obtained from + * CPU cycles as follows: + * + * intr_timer_usec = intr_timer_cycles * divisor / multiplier + * + * in: none + * out: (u32)a0 = multiplier + * (u32)a1 = divisor + * (u32)a2 = maximum timer value in usec + */ + CMD_INTR_COAL_CONVERT = _CMDC(_CMD_DIR_READ, _CMD_VTYPE_ALL, 50), }; /* CMD_ENABLE2 flags */ diff --git a/drivers/net/enic/vnic_enet.h b/drivers/net/enic/vnic_enet.h index 061ad8780796..609542848e02 100644 --- a/drivers/net/enic/vnic_enet.h +++ b/drivers/net/enic/vnic_enet.h @@ -20,10 +20,6 @@ #ifndef _VNIC_ENIC_H_ #define _VNIC_ENIC_H_ -/* Hardware intr coalesce timer is in units of 1.5us */ -#define INTR_COALESCE_USEC_TO_HW(usec) ((usec) * 2/3) -#define INTR_COALESCE_HW_TO_USEC(usec) ((usec) * 3/2) - /* Device-specific region: enet configuration */ struct vnic_enet_config { u32 flags; diff --git a/drivers/net/enic/vnic_intr.c b/drivers/net/enic/vnic_intr.c index 3873771d75cc..0ca107f7bc8c 100644 --- a/drivers/net/enic/vnic_intr.c +++ b/drivers/net/enic/vnic_intr.c @@ -46,7 +46,7 @@ int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr, return 0; } -void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer, +void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer, unsigned int coalescing_type, unsigned int mask_on_assertion) { vnic_intr_coalescing_timer_set(intr, coalescing_timer); @@ -56,9 +56,10 @@ void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer, } void vnic_intr_coalescing_timer_set(struct vnic_intr *intr, - unsigned int coalescing_timer) + u32 coalescing_timer) { - iowrite32(coalescing_timer, &intr->ctrl->coalescing_timer); + iowrite32(vnic_dev_intr_coal_timer_usec_to_hw(intr->vdev, + coalescing_timer), &intr->ctrl->coalescing_timer); } void vnic_intr_clean(struct vnic_intr *intr) diff --git a/drivers/net/enic/vnic_intr.h b/drivers/net/enic/vnic_intr.h index 09dc0b73ff46..2b1636392294 100644 --- a/drivers/net/enic/vnic_intr.h +++ b/drivers/net/enic/vnic_intr.h @@ -24,8 +24,6 @@ #include "vnic_dev.h" -#define VNIC_INTR_TIMER_MAX 0xffff - #define VNIC_INTR_TIMER_TYPE_ABS 0 #define VNIC_INTR_TIMER_TYPE_QUIET 1 @@ -104,10 +102,10 @@ static inline u32 vnic_intr_legacy_pba(u32 __iomem *legacy_pba) void vnic_intr_free(struct vnic_intr *intr); int vnic_intr_alloc(struct vnic_dev *vdev, struct vnic_intr *intr, unsigned int index); -void vnic_intr_init(struct vnic_intr *intr, unsigned int coalescing_timer, +void vnic_intr_init(struct vnic_intr *intr, u32 coalescing_timer, unsigned int coalescing_type, unsigned int mask_on_assertion); void vnic_intr_coalescing_timer_set(struct vnic_intr *intr, - unsigned int coalescing_timer); + u32 coalescing_timer); void vnic_intr_clean(struct vnic_intr *intr); #endif /* _VNIC_INTR_H_ */ diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index b6c296f4b4d5..242bf524273e 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -964,11 +964,9 @@ static void veth_set_multicast_list(struct net_device *dev) u8 *addr = ha->addr; u64 xaddr = 0; - if (addr[0] & 0x01) {/* multicast address? */ - memcpy(&xaddr, addr, ETH_ALEN); - port->mcast_addr[port->num_mcast] = xaddr; - port->num_mcast++; - } + memcpy(&xaddr, addr, ETH_ALEN); + port->mcast_addr[port->num_mcast] = xaddr; + port->num_mcast++; } } diff --git a/drivers/net/jme.c b/drivers/net/jme.c index b5b174a8c149..6b2a5e744255 100644 --- a/drivers/net/jme.c +++ b/drivers/net/jme.c @@ -271,9 +271,7 @@ jme_reset_mac_processor(struct jme_adapter *jme) static inline void jme_clear_pm(struct jme_adapter *jme) { - jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs); - pci_set_power_state(jme->pdev, PCI_D0); - device_set_wakeup_enable(&jme->pdev->dev, false); + jwrite32(jme, JME_PMCS, PMCS_STMASK | jme->reg_pmcs); } static int @@ -1817,11 +1815,9 @@ jme_powersave_phy(struct jme_adapter *jme) { if (jme->reg_pmcs) { jme_set_100m_half(jme); - if (jme->reg_pmcs & (PMCS_LFEN | PMCS_LREN)) jme_wait_link(jme); - - jwrite32(jme, JME_PMCS, jme->reg_pmcs); + jme_clear_pm(jme); } else { jme_phy_off(jme); } @@ -2529,8 +2525,7 @@ jme_set_wol(struct net_device *netdev, jme->reg_pmcs |= PMCS_MFEN; jwrite32(jme, JME_PMCS, jme->reg_pmcs); - - device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs); + device_set_wakeup_enable(&jme->pdev->dev, !!(jme->reg_pmcs)); return 0; } @@ -3058,6 +3053,9 @@ jme_init_one(struct pci_dev *pdev, jme->mii_if.mdio_write = jme_mdio_write; jme_clear_pm(jme); + pci_set_power_state(jme->pdev, PCI_D0); + device_set_wakeup_enable(&pdev->dev, true); + jme_set_phyfifo_5level(jme); jme->pcirev = pdev->revision; if (!jme->fpgaver) @@ -3135,8 +3133,9 @@ jme_shutdown(struct pci_dev *pdev) pci_pme_active(pdev, true); } -#ifdef CONFIG_PM -static int jme_suspend(struct device *dev) +#ifdef CONFIG_PM_SLEEP +static int +jme_suspend(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct net_device *netdev = pci_get_drvdata(pdev); @@ -3175,14 +3174,14 @@ static int jme_suspend(struct device *dev) return 0; } -static int jme_resume(struct device *dev) +static int +jme_resume(struct device *dev) { struct pci_dev *pdev = to_pci_dev(dev); struct net_device *netdev = pci_get_drvdata(pdev); struct jme_adapter *jme = netdev_priv(netdev); - jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs); - + jme_clear_pm(jme); jme_phy_on(jme); if (test_bit(JME_FLAG_SSET, &jme->flags)) jme_set_settings(netdev, &jme->old_ecmd); diff --git a/drivers/net/jme.h b/drivers/net/jme.h index 0d5da06489d8..1481a62a1f36 100644 --- a/drivers/net/jme.h +++ b/drivers/net/jme.h @@ -852,6 +852,7 @@ enum jme_ghc_txmac_clk { * Power management control and status register */ enum jme_pmcs_bit_masks { + PMCS_STMASK = 0xFFFF0000, PMCS_WF7DET = 0x80000000, PMCS_WF6DET = 0x40000000, PMCS_WF5DET = 0x20000000, @@ -863,6 +864,7 @@ enum jme_pmcs_bit_masks { PMCS_LFDET = 0x00040000, PMCS_LRDET = 0x00020000, PMCS_MFDET = 0x00010000, + PMCS_ENMASK = 0x0000FFFF, PMCS_WF7EN = 0x00008000, PMCS_WF6EN = 0x00004000, PMCS_WF5EN = 0x00002000, diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index e5454502df6b..9899a7947718 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -36,8 +36,8 @@ #define _QLCNIC_LINUX_MAJOR 5 #define _QLCNIC_LINUX_MINOR 0 -#define _QLCNIC_LINUX_SUBVERSION 19 -#define QLCNIC_LINUX_VERSIONID "5.0.19" +#define _QLCNIC_LINUX_SUBVERSION 20 +#define QLCNIC_LINUX_VERSIONID "5.0.20" #define QLCNIC_DRV_IDC_VER 0x01 #define QLCNIC_DRIVER_VERSION ((_QLCNIC_LINUX_MAJOR << 16) |\ (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION)) @@ -782,6 +782,7 @@ struct qlcnic_mac_list_s { #define QLCNIC_IP_DOWN 3 #define QLCNIC_ILB_MODE 0x1 +#define QLCNIC_ELB_MODE 0x2 #define QLCNIC_LINKEVENT 0x1 #define QLCNIC_LB_RESPONSE 0x2 diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 743035e4538d..3ea04e7da917 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -85,7 +85,8 @@ static const char qlcnic_gstrings_test[][ETH_GSTRING_LEN] = { "Register_Test_on_offline", "Link_Test_on_offline", "Interrupt_Test_offline", - "Loopback_Test_offline" + "Internal_Loopback_offline", + "External_Loopback_offline" }; #define QLCNIC_TEST_LEN ARRAY_SIZE(qlcnic_gstrings_test) @@ -709,7 +710,7 @@ int qlcnic_check_loopback_buff(unsigned char *data, u8 mac[]) return memcmp(data, buff, QLCNIC_ILB_PKT_SIZE); } -static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter) +static int qlcnic_do_lb_test(struct qlcnic_adapter *adapter) { struct qlcnic_recv_context *recv_ctx = adapter->recv_ctx; struct qlcnic_host_sds_ring *sds_ring = &recv_ctx->sds_rings[0]; @@ -735,19 +736,19 @@ static int qlcnic_do_ilb_test(struct qlcnic_adapter *adapter) dev_kfree_skb_any(skb); if (!adapter->diag_cnt) - dev_warn(&adapter->pdev->dev, "ILB Test: %dth packet" + dev_warn(&adapter->pdev->dev, "LB Test: %dth packet" " not recevied\n", i + 1); else cnt++; } if (cnt != i) { - dev_warn(&adapter->pdev->dev, "ILB Test failed\n"); + dev_warn(&adapter->pdev->dev, "LB Test failed\n"); return -1; } return 0; } -static int qlcnic_iloopback_test(struct net_device *netdev) +static int qlcnic_loopback_test(struct net_device *netdev, u8 mode) { struct qlcnic_adapter *adapter = netdev_priv(netdev); int max_sds_rings = adapter->max_sds_rings; @@ -755,7 +756,8 @@ static int qlcnic_iloopback_test(struct net_device *netdev) int loop = 0; int ret; - netdev_info(netdev, "%s: in progress\n", __func__); + netdev_info(netdev, "%s loopback test in progress\n", + mode == QLCNIC_ILB_MODE ? "internal" : "external"); if (adapter->op_mode == QLCNIC_NON_PRIV_FUNC) { netdev_warn(netdev, "Loopback test not supported for non " "privilege function\n"); @@ -772,7 +774,7 @@ static int qlcnic_iloopback_test(struct net_device *netdev) sds_ring = &adapter->recv_ctx->sds_rings[0]; - ret = qlcnic_set_lb_mode(adapter, QLCNIC_ILB_MODE); + ret = qlcnic_set_lb_mode(adapter, mode); if (ret) goto free_res; @@ -790,7 +792,7 @@ static int qlcnic_iloopback_test(struct net_device *netdev) goto free_res; } - ret = qlcnic_do_ilb_test(adapter); + ret = qlcnic_do_lb_test(adapter); qlcnic_clear_lb_mode(adapter); @@ -822,10 +824,16 @@ qlcnic_diag_test(struct net_device *dev, struct ethtool_test *eth_test, if (data[2]) eth_test->flags |= ETH_TEST_FL_FAILED; - data[3] = qlcnic_iloopback_test(dev); + data[3] = qlcnic_loopback_test(dev, QLCNIC_ILB_MODE); if (data[3]) eth_test->flags |= ETH_TEST_FL_FAILED; + if (eth_test->flags & ETH_TEST_FL_EXTERNAL_LB) { + data[4] = qlcnic_loopback_test(dev, QLCNIC_ELB_MODE); + if (data[4]) + eth_test->flags |= ETH_TEST_FL_FAILED; + eth_test->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE; + } } } diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index 9d5bee03a587..6ec1baa85f6a 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -1303,7 +1303,8 @@ qlcnic_handle_linkevent(struct qlcnic_adapter *adapter, dev_info(&netdev->dev, "unsupported cable length %d\n", cable_len); - if (!link_status && (lb_status == 1)) + if (!link_status && (lb_status == QLCNIC_ILB_MODE || + lb_status == QLCNIC_ELB_MODE)) adapter->ahw->loopback_state |= QLCNIC_LINKEVENT; qlcnic_advert_link_change(adapter, link_status); diff --git a/drivers/net/tulip/de4x5.c b/drivers/net/tulip/de4x5.c index efaa1d69b720..d8db2b664ac2 100644 --- a/drivers/net/tulip/de4x5.c +++ b/drivers/net/tulip/de4x5.c @@ -1964,9 +1964,7 @@ SetMulticastFilter(struct net_device *dev) omr |= OMR_PM; /* Pass all multicasts */ } else if (lp->setup_f == HASH_PERF) { /* Hash Filtering */ netdev_for_each_mc_addr(ha, dev) { - addrs = ha->addr; - if ((*addrs & 0x01) == 1) { /* multicast address? */ - crc = ether_crc_le(ETH_ALEN, addrs); + crc = ether_crc_le(ETH_ALEN, ha->addr); hashcode = crc & HASH_BITS; /* hashcode is 9 LSb of CRC */ byte = hashcode >> 3; /* bit[3-8] -> byte in filter */ @@ -1977,7 +1975,6 @@ SetMulticastFilter(struct net_device *dev) byte -= 1; } lp->setup_frame[byte] |= bit; - } } } else { /* Perfect filtering */ netdev_for_each_mc_addr(ha, dev) { diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 3127700f348b..d3465ab50e56 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -2030,11 +2030,6 @@ static void ucc_geth_set_multi(struct net_device *dev) out_be32(&p_82xx_addr_filt->gaddr_l, 0x0); netdev_for_each_mc_addr(ha, dev) { - /* Only support group multicast for now. - */ - if (!is_multicast_ether_addr(ha->addr)) - continue; - /* Ask CPM to run CRC and set bit in * filter mask. */ diff --git a/drivers/net/veth.c b/drivers/net/veth.c index 4b6db3b6c5d5..9eb92bfa92ab 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c @@ -126,9 +126,6 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev) stats = this_cpu_ptr(priv->stats); rcv_stats = this_cpu_ptr(rcv_priv->stats); - if (!(rcv->flags & IFF_UP)) - goto tx_drop; - /* don't change ip_summed == CHECKSUM_PARTIAL, as that will cause bad checksum on forwarded packets */ if (skb->ip_summed == CHECKSUM_NONE && diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index be3686a298da..fbea637eb742 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -40,6 +40,15 @@ module_param(gso, bool, 0444); #define VIRTNET_SEND_COMMAND_SG_MAX 2 +struct virtnet_stats { + struct u64_stats_sync syncp; + u64 tx_bytes; + u64 tx_packets; + + u64 rx_bytes; + u64 rx_packets; +}; + struct virtnet_info { struct virtio_device *vdev; struct virtqueue *rvq, *svq, *cvq; @@ -56,6 +65,9 @@ struct virtnet_info { /* Host will merge rx buffers for big packets (shake it! shake it!) */ bool mergeable_rx_bufs; + /* Active statistics */ + struct virtnet_stats __percpu *stats; + /* Work struct for refilling if we run low on memory. */ struct delayed_work refill; @@ -209,7 +221,6 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb) skb->dev->stats.rx_length_errors++; return -EINVAL; } - page = virtqueue_get_buf(vi->rvq, &len); if (!page) { pr_debug("%s: rx error: %d buffers missing\n", @@ -217,6 +228,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb) skb->dev->stats.rx_length_errors++; return -EINVAL; } + if (len > PAGE_SIZE) len = PAGE_SIZE; @@ -230,6 +242,7 @@ static int receive_mergeable(struct virtnet_info *vi, struct sk_buff *skb) static void receive_buf(struct net_device *dev, void *buf, unsigned int len) { struct virtnet_info *vi = netdev_priv(dev); + struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats); struct sk_buff *skb; struct page *page; struct skb_vnet_hdr *hdr; @@ -265,8 +278,11 @@ static void receive_buf(struct net_device *dev, void *buf, unsigned int len) hdr = skb_vnet_hdr(skb); skb->truesize += skb->data_len; - dev->stats.rx_bytes += skb->len; - dev->stats.rx_packets++; + + u64_stats_update_begin(&stats->syncp); + stats->rx_bytes += skb->len; + stats->rx_packets++; + u64_stats_update_end(&stats->syncp); if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { pr_debug("Needs csum!\n"); @@ -515,11 +531,16 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi) { struct sk_buff *skb; unsigned int len, tot_sgs = 0; + struct virtnet_stats __percpu *stats = this_cpu_ptr(vi->stats); while ((skb = virtqueue_get_buf(vi->svq, &len)) != NULL) { pr_debug("Sent skb %p\n", skb); - vi->dev->stats.tx_bytes += skb->len; - vi->dev->stats.tx_packets++; + + u64_stats_update_begin(&stats->syncp); + stats->tx_bytes += skb->len; + stats->tx_packets++; + u64_stats_update_end(&stats->syncp); + tot_sgs += skb_vnet_hdr(skb)->num_sg; dev_kfree_skb_any(skb); } @@ -641,6 +662,40 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p) return 0; } +static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev, + struct rtnl_link_stats64 *tot) +{ + struct virtnet_info *vi = netdev_priv(dev); + int cpu; + unsigned int start; + + for_each_possible_cpu(cpu) { + struct virtnet_stats __percpu *stats + = per_cpu_ptr(vi->stats, cpu); + u64 tpackets, tbytes, rpackets, rbytes; + + do { + start = u64_stats_fetch_begin(&stats->syncp); + tpackets = stats->tx_packets; + tbytes = stats->tx_bytes; + rpackets = stats->rx_packets; + rbytes = stats->rx_bytes; + } while (u64_stats_fetch_retry(&stats->syncp, start)); + + tot->rx_packets += rpackets; + tot->tx_packets += tpackets; + tot->rx_bytes += rbytes; + tot->tx_bytes += tbytes; + } + + tot->tx_dropped = dev->stats.tx_dropped; + tot->rx_dropped = dev->stats.rx_dropped; + tot->rx_length_errors = dev->stats.rx_length_errors; + tot->rx_frame_errors = dev->stats.rx_frame_errors; + + return tot; +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void virtnet_netpoll(struct net_device *dev) { @@ -650,6 +705,14 @@ static void virtnet_netpoll(struct net_device *dev) } #endif +static void virtnet_free(struct net_device *dev) +{ + struct virtnet_info *vi = netdev_priv(dev); + + free_percpu(vi->stats); + free_netdev(dev); +} + static int virtnet_open(struct net_device *dev) { struct virtnet_info *vi = netdev_priv(dev); @@ -835,6 +898,7 @@ static const struct net_device_ops virtnet_netdev = { .ndo_set_mac_address = virtnet_set_mac_address, .ndo_set_rx_mode = virtnet_set_rx_mode, .ndo_change_mtu = virtnet_change_mtu, + .ndo_get_stats64 = virtnet_stats, .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid, .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid, #ifdef CONFIG_NET_POLL_CONTROLLER @@ -895,6 +959,8 @@ static int virtnet_probe(struct virtio_device *vdev) /* Set up network device as normal. */ dev->netdev_ops = &virtnet_netdev; dev->features = NETIF_F_HIGHDMA; + dev->destructor = virtnet_free; + SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops); SET_NETDEV_DEV(dev, &vdev->dev); @@ -939,6 +1005,11 @@ static int virtnet_probe(struct virtio_device *vdev) vi->vdev = vdev; vdev->priv = vi; vi->pages = NULL; + vi->stats = alloc_percpu(struct virtnet_stats); + err = -ENOMEM; + if (vi->stats == NULL) + goto free; + INIT_DELAYED_WORK(&vi->refill, refill_work); sg_init_table(vi->rx_sg, ARRAY_SIZE(vi->rx_sg)); sg_init_table(vi->tx_sg, ARRAY_SIZE(vi->tx_sg)); @@ -958,7 +1029,7 @@ static int virtnet_probe(struct virtio_device *vdev) err = vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names); if (err) - goto free; + goto free_stats; vi->rvq = vqs[0]; vi->svq = vqs[1]; @@ -1003,6 +1074,8 @@ unregister: cancel_delayed_work_sync(&vi->refill); free_vqs: vdev->config->del_vqs(vdev); +free_stats: + free_percpu(vi->stats); free: free_netdev(dev); return err; diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index 8d7aa43dfba5..44b707197258 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -284,7 +284,7 @@ static netdev_tx_t wanxl_xmit(struct sk_buff *skb, struct net_device *dev) printk(KERN_DEBUG "%s: transmitter buffer full\n", dev->name); #endif netif_stop_queue(dev); - spin_unlock_irq(&port->lock); + spin_unlock(&port->lock); return NETDEV_TX_BUSY; /* request packet to be queued */ } diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 0e4851b8a773..fd00f25d9850 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1743,3 +1743,4 @@ failed_init: module_init(netback_init); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("xen-backend:vif"); |