* [PATCH net-next 09/16] sfc: Remove bogus call to efx_release_tx_buffers()
From: Ben Hutchings @ 2013-08-25 23:06 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1377471363.2586.69.camel@deadeye.wl.decadent.org.uk>
efx_unregister_netdev() should not call efx_release_tx_buffers()
directly, as it is already done when closing the device:
efx_net_stop() -> efx_stop_all() -> efx_stop_datapath() ->
efx_fini_tx_queue() -> efx_release_tx_buffers().
(This was presumably a workaround for a race between efx_stop_all()
and the data path that has since been properly fixed.)
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/efx.c | 11 -----------
1 files changed, 0 insertions(+), 11 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index ee9242c..0c3c0c1 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -2156,22 +2156,11 @@ fail_locked:
static void efx_unregister_netdev(struct efx_nic *efx)
{
- struct efx_channel *channel;
- struct efx_tx_queue *tx_queue;
-
if (!efx->net_dev)
return;
BUG_ON(netdev_priv(efx->net_dev) != efx);
- /* Free up any skbs still remaining. This has to happen before
- * we try to unregister the netdev as running their destructors
- * may be needed to get the device ref. count to 0. */
- efx_for_each_channel(channel, efx) {
- efx_for_each_channel_tx_queue(tx_queue, channel)
- efx_release_tx_buffers(tx_queue);
- }
-
strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 08/16] sfc: Stop RX refill before flushing RX queues
From: Ben Hutchings @ 2013-08-25 23:05 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1377471363.2586.69.camel@deadeye.wl.decadent.org.uk>
rx_queue::enabled guards refill, so rename it to reflect that. Clear
it at the start of the queue teardown process rather than waiting for
the RX queue to be flushed.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/efx.c | 9 +++++++--
drivers/net/ethernet/sfc/net_driver.h | 4 ++--
drivers/net/ethernet/sfc/nic.c | 1 -
drivers/net/ethernet/sfc/rx.c | 8 ++++----
4 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index a7818d1..ee9242c 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -248,8 +248,7 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
efx_channel_get_rx_queue(channel);
efx_rx_flush_packet(channel);
- if (rx_queue->enabled)
- efx_fast_push_rx_descriptors(rx_queue);
+ efx_fast_push_rx_descriptors(rx_queue);
}
return spent;
@@ -647,6 +646,12 @@ static void efx_stop_datapath(struct efx_nic *efx)
EFX_ASSERT_RESET_SERIALISED(efx);
BUG_ON(efx->port_enabled);
+ /* Stop RX refill */
+ efx_for_each_channel(channel, efx) {
+ efx_for_each_channel_rx_queue(rx_queue, channel)
+ rx_queue->refill_enabled = false;
+ }
+
/* Only perform flush if dma is enabled */
if (dev->is_busmaster && efx->state != STATE_RECOVERY) {
rc = efx_nic_flush_queues(efx);
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 7c96372..c9f7989 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -286,7 +286,7 @@ struct efx_rx_page_state {
* @buffer: The software buffer ring
* @rxd: The hardware descriptor ring
* @ptr_mask: The size of the ring minus 1.
- * @enabled: Receive queue enabled indicator.
+ * @refill_enabled: Enable refill whenever fill level is low
* @flush_pending: Set when a RX flush is pending. Has the same lifetime as
* @rxq_flush_pending.
* @added_count: Number of buffers added to the receive queue.
@@ -317,7 +317,7 @@ struct efx_rx_queue {
struct efx_rx_buffer *buffer;
struct efx_special_buffer rxd;
unsigned int ptr_mask;
- bool enabled;
+ bool refill_enabled;
bool flush_pending;
unsigned int added_count;
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 2d0a584..deb0ee04 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -1204,7 +1204,6 @@ efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
* queue. Refill it here */
efx_fast_push_rx_descriptors(rx_queue);
} else if (rx_queue && magic == EFX_CHANNEL_MAGIC_RX_DRAIN(rx_queue)) {
- rx_queue->enabled = false;
efx_handle_drain_event(channel);
} else if (code == _EFX_CHANNEL_MAGIC_TX_DRAIN) {
efx_handle_drain_event(channel);
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c
index 6af9cfd..8b482de 100644
--- a/drivers/net/ethernet/sfc/rx.c
+++ b/drivers/net/ethernet/sfc/rx.c
@@ -326,6 +326,9 @@ void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue)
unsigned int fill_level, batch_size;
int space, rc = 0;
+ if (!rx_queue->refill_enabled)
+ return;
+
/* Calculate current fill level, and exit if we don't need to fill */
fill_level = (rx_queue->added_count - rx_queue->removed_count);
EFX_BUG_ON_PARANOID(fill_level > rx_queue->efx->rxq_entries);
@@ -738,9 +741,9 @@ void efx_init_rx_queue(struct efx_rx_queue *rx_queue)
rx_queue->max_fill = max_fill;
rx_queue->fast_fill_trigger = trigger;
+ rx_queue->refill_enabled = true;
/* Set up RX descriptor ring */
- rx_queue->enabled = true;
efx_nic_init_rx(rx_queue);
}
@@ -753,9 +756,6 @@ void efx_fini_rx_queue(struct efx_rx_queue *rx_queue)
netif_dbg(rx_queue->efx, drv, rx_queue->efx->net_dev,
"shutting down RX queue %d\n", efx_rx_queue_index(rx_queue));
- /* A flush failure might have left rx_queue->enabled */
- rx_queue->enabled = false;
-
del_timer_sync(&rx_queue->slow_fill);
efx_nic_fini_rx(rx_queue);
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 07/16] sfc: Limit scope of a Falcon A1 IRQ workaround
From: Ben Hutchings @ 2013-08-25 23:03 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1377471363.2586.69.camel@deadeye.wl.decadent.org.uk>
We unconditionally acknowledge legacy interrupts just before disabling
them. This workaround is needed on Falcon A1 but probably not on
later chips where the legacy interrupt mechanism is different. It was
also originally done after the IRQ handler was removed, not before.
Restore the original behaviour for Falcon A1 only by doing this
acknowledgement in the efx_nic_type::fini operation.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/falcon.c | 4 ++--
drivers/net/ethernet/sfc/nic.c | 7 -------
drivers/net/ethernet/sfc/nic.h | 1 -
3 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index f8de382..4492129 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -336,7 +336,7 @@ static void falcon_prepare_flush(struct efx_nic *efx)
*
* NB most hardware supports MSI interrupts
*/
-inline void falcon_irq_ack_a1(struct efx_nic *efx)
+static inline void falcon_irq_ack_a1(struct efx_nic *efx)
{
efx_dword_t reg;
@@ -2343,7 +2343,7 @@ const struct efx_nic_type falcon_a1_nic_type = {
.remove = falcon_remove_nic,
.init = falcon_init_nic,
.dimension_resources = falcon_dimension_resources,
- .fini = efx_port_dummy_op_void,
+ .fini = falcon_irq_ack_a1,
.monitor = falcon_monitor,
.map_reset_reason = falcon_map_reset_reason,
.map_reset_flags = falcon_map_reset_flags,
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index c17d659..2d0a584 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -1781,7 +1781,6 @@ int efx_nic_init_interrupt(struct efx_nic *efx)
void efx_nic_fini_interrupt(struct efx_nic *efx)
{
struct efx_channel *channel;
- efx_oword_t reg;
#ifdef CONFIG_RFS_ACCEL
free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
@@ -1792,12 +1791,6 @@ void efx_nic_fini_interrupt(struct efx_nic *efx)
efx_for_each_channel(channel, efx)
free_irq(channel->irq, &efx->msi_context[channel->channel]);
- /* ACK legacy interrupt */
- if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
- efx_reado(efx, ®, FR_BZ_INT_ISR0);
- else
- falcon_irq_ack_a1(efx);
-
/* Disable legacy interrupt */
if (efx->legacy_irq)
free_irq(efx->legacy_irq, efx);
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 9120e8b..33aa120 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -308,7 +308,6 @@ extern void efx_nic_disable_interrupts(struct efx_nic *efx);
extern void efx_nic_fini_interrupt(struct efx_nic *efx);
extern irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx);
extern irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id);
-extern void falcon_irq_ack_a1(struct efx_nic *efx);
static inline int efx_nic_event_test_irq_cpu(struct efx_channel *channel)
{
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 06/16] sfc: Rework IRQ enable/disable
From: Ben Hutchings @ 2013-08-25 23:03 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1377471363.2586.69.camel@deadeye.wl.decadent.org.uk>
There are many problems with the current efx_stop_interrupts() and
efx_start_interrupts():
1. On Siena, it is unsafe to disable the master IRQ enable bit
(DRV_INT_EN_KER) while any IRQ sources are enabled.
2. On EF10 there is no master IRQ enable bit, so we cannot expect to
defer IRQs without tearing down event queues. (Though I don't think
we will need to keep any event queues around while the device is down,
as we do for VFDI on Siena.)
3. synchronize_irq() only waits for a running IRQ handler to finish,
not for any propagation through IRQ controllers. Therefore an IRQ may
still be received and handled after efx_stop_interrupts() returns.
IRQ handlers can then race with channel reallocation.
To fix this:
a. Introduce a software IRQ enable flag. So long as this is clear,
IRQ handlers will only acknowledge IRQs and not touch the channel
structures.
b. Define a new struct efx_msi_context as the context for MSIs. This
is never reallocated and is sufficient to find the software enable
flag and the channel structure. It also includes the channel/IRQ
name, which was previously separated out as it must also not be
reallocated.
c. Split efx_{start,stop}_interrupts() into
efx_{,soft_}_{enable,disable}_interrupts(). The 'soft' functions
don't touch the hardware master enable flag (if it exists) and don't
reinitialise or tear down channels with the keep_eventq flag set.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/efx.c | 91 ++++++++++++++++++++++-----------
drivers/net/ethernet/sfc/falcon.c | 3 +
drivers/net/ethernet/sfc/net_driver.h | 24 +++++++--
drivers/net/ethernet/sfc/nic.c | 53 ++++++++++---------
4 files changed, 112 insertions(+), 59 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 2b2dba1..a7818d1 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -191,8 +191,8 @@ MODULE_PARM_DESC(debug, "Bitmapped debugging message enable value");
*
*************************************************************************/
-static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq);
-static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq);
+static void efx_soft_enable_interrupts(struct efx_nic *efx);
+static void efx_soft_disable_interrupts(struct efx_nic *efx);
static void efx_remove_channel(struct efx_channel *channel);
static void efx_remove_channels(struct efx_nic *efx);
static const struct efx_channel_type efx_default_channel_type;
@@ -520,8 +520,8 @@ static void efx_set_channel_names(struct efx_nic *efx)
efx_for_each_channel(channel, efx)
channel->type->get_name(channel,
- efx->channel_name[channel->channel],
- sizeof(efx->channel_name[0]));
+ efx->msi_context[channel->channel].name,
+ sizeof(efx->msi_context[0].name));
}
static int efx_probe_channels(struct efx_nic *efx)
@@ -746,7 +746,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
efx_device_detach_sync(efx);
efx_stop_all(efx);
- efx_stop_interrupts(efx, true);
+ efx_soft_disable_interrupts(efx);
/* Clone channels (where possible) */
memset(other_channel, 0, sizeof(other_channel));
@@ -796,7 +796,7 @@ out:
}
}
- efx_start_interrupts(efx, true);
+ efx_soft_enable_interrupts(efx);
efx_start_all(efx);
netif_device_attach(efx->net_dev);
return rc;
@@ -1329,23 +1329,17 @@ static int efx_probe_interrupts(struct efx_nic *efx)
return 0;
}
-/* Enable interrupts, then probe and start the event queues */
-static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq)
+static void efx_soft_enable_interrupts(struct efx_nic *efx)
{
struct efx_channel *channel;
BUG_ON(efx->state == STATE_DISABLED);
- if (efx->eeh_disabled_legacy_irq) {
- enable_irq(efx->legacy_irq);
- efx->eeh_disabled_legacy_irq = false;
- }
- if (efx->legacy_irq)
- efx->legacy_irq_enabled = true;
- efx_nic_enable_interrupts(efx);
+ efx->irq_soft_enabled = true;
+ smp_wmb();
efx_for_each_channel(channel, efx) {
- if (!channel->type->keep_eventq || !may_keep_eventq)
+ if (!channel->type->keep_eventq)
efx_init_eventq(channel);
efx_start_eventq(channel);
}
@@ -1353,7 +1347,7 @@ static void efx_start_interrupts(struct efx_nic *efx, bool may_keep_eventq)
efx_mcdi_mode_event(efx);
}
-static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq)
+static void efx_soft_disable_interrupts(struct efx_nic *efx)
{
struct efx_channel *channel;
@@ -1362,22 +1356,57 @@ static void efx_stop_interrupts(struct efx_nic *efx, bool may_keep_eventq)
efx_mcdi_mode_poll(efx);
- efx_nic_disable_interrupts(efx);
- if (efx->legacy_irq) {
+ efx->irq_soft_enabled = false;
+ smp_wmb();
+
+ if (efx->legacy_irq)
synchronize_irq(efx->legacy_irq);
- efx->legacy_irq_enabled = false;
- }
efx_for_each_channel(channel, efx) {
if (channel->irq)
synchronize_irq(channel->irq);
efx_stop_eventq(channel);
- if (!channel->type->keep_eventq || !may_keep_eventq)
+ if (!channel->type->keep_eventq)
efx_fini_eventq(channel);
}
}
+static void efx_enable_interrupts(struct efx_nic *efx)
+{
+ struct efx_channel *channel;
+
+ BUG_ON(efx->state == STATE_DISABLED);
+
+ if (efx->eeh_disabled_legacy_irq) {
+ enable_irq(efx->legacy_irq);
+ efx->eeh_disabled_legacy_irq = false;
+ }
+
+ efx_nic_enable_interrupts(efx);
+
+ efx_for_each_channel(channel, efx) {
+ if (channel->type->keep_eventq)
+ efx_init_eventq(channel);
+ }
+
+ efx_soft_enable_interrupts(efx);
+}
+
+static void efx_disable_interrupts(struct efx_nic *efx)
+{
+ struct efx_channel *channel;
+
+ efx_soft_disable_interrupts(efx);
+
+ efx_for_each_channel(channel, efx) {
+ if (channel->type->keep_eventq)
+ efx_fini_eventq(channel);
+ }
+
+ efx_nic_disable_interrupts(efx);
+}
+
static void efx_remove_interrupts(struct efx_nic *efx)
{
struct efx_channel *channel;
@@ -2160,7 +2189,7 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method)
EFX_ASSERT_RESET_SERIALISED(efx);
efx_stop_all(efx);
- efx_stop_interrupts(efx, false);
+ efx_disable_interrupts(efx);
mutex_lock(&efx->mac_lock);
if (efx->port_initialized && method != RESET_TYPE_INVISIBLE)
@@ -2199,7 +2228,7 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method, bool ok)
efx->type->reconfigure_mac(efx);
- efx_start_interrupts(efx, false);
+ efx_enable_interrupts(efx);
efx_restore_filters(efx);
efx_sriov_reset(efx);
@@ -2464,6 +2493,8 @@ static int efx_init_struct(struct efx_nic *efx,
efx->channel[i] = efx_alloc_channel(efx, i, NULL);
if (!efx->channel[i])
goto fail;
+ efx->msi_context[i].efx = efx;
+ efx->msi_context[i].index = i;
}
EFX_BUG_ON_PARANOID(efx->type->phys_addr_channels > EFX_MAX_CHANNELS);
@@ -2516,7 +2547,7 @@ static void efx_pci_remove_main(struct efx_nic *efx)
BUG_ON(efx->state == STATE_READY);
cancel_work_sync(&efx->reset_work);
- efx_stop_interrupts(efx, false);
+ efx_disable_interrupts(efx);
efx_nic_fini_interrupt(efx);
efx_fini_port(efx);
efx->type->fini(efx);
@@ -2538,7 +2569,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
/* Mark the NIC as fini, then stop the interface */
rtnl_lock();
dev_close(efx->net_dev);
- efx_stop_interrupts(efx, false);
+ efx_disable_interrupts(efx);
rtnl_unlock();
efx_sriov_fini(efx);
@@ -2640,7 +2671,7 @@ static int efx_pci_probe_main(struct efx_nic *efx)
rc = efx_nic_init_interrupt(efx);
if (rc)
goto fail5;
- efx_start_interrupts(efx, false);
+ efx_enable_interrupts(efx);
return 0;
@@ -2761,7 +2792,7 @@ static int efx_pm_freeze(struct device *dev)
efx_device_detach_sync(efx);
efx_stop_all(efx);
- efx_stop_interrupts(efx, false);
+ efx_disable_interrupts(efx);
}
rtnl_unlock();
@@ -2776,7 +2807,7 @@ static int efx_pm_thaw(struct device *dev)
rtnl_lock();
if (efx->state != STATE_DISABLED) {
- efx_start_interrupts(efx, false);
+ efx_enable_interrupts(efx);
mutex_lock(&efx->mac_lock);
efx->phy_op->reconfigure(efx);
@@ -2879,7 +2910,7 @@ static pci_ers_result_t efx_io_error_detected(struct pci_dev *pdev,
efx_device_detach_sync(efx);
efx_stop_all(efx);
- efx_stop_interrupts(efx, false);
+ efx_disable_interrupts(efx);
status = PCI_ERS_RESULT_NEED_RESET;
} else {
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index f87710e..f8de382 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -367,6 +367,9 @@ irqreturn_t falcon_legacy_interrupt_a1(int irq, void *dev_id)
"IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
+ if (!likely(ACCESS_ONCE(efx->irq_soft_enabled)))
+ return IRQ_HANDLED;
+
/* Check to see if we have a serious error condition */
syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
if (unlikely(syserr))
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index ad89d7d..7c96372 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -420,6 +420,21 @@ struct efx_channel {
};
/**
+ * struct efx_msi_context - Context for each MSI
+ * @efx: The associated NIC
+ * @index: Index of the channel/IRQ
+ * @name: Name of the channel/IRQ
+ *
+ * Unlike &struct efx_channel, this is never reallocated and is always
+ * safe for the IRQ handler to access.
+ */
+struct efx_msi_context {
+ struct efx_nic *efx;
+ unsigned int index;
+ char name[IFNAMSIZ + 6];
+};
+
+/**
* struct efx_channel_type - distinguishes traffic and extra channels
* @handle_no_channel: Handle failure to allocate an extra channel
* @pre_probe: Set up extra state prior to initialisation
@@ -669,7 +684,6 @@ struct vfdi_status;
* @pci_dev: The PCI device
* @type: Controller type attributes
* @legacy_irq: IRQ number
- * @legacy_irq_enabled: Are IRQs enabled on NIC (INT_EN_KER register)?
* @workqueue: Workqueue for port reconfigures and the HW monitor.
* Work items do not hold and must not acquire RTNL.
* @workqueue_name: Name of workqueue
@@ -686,7 +700,7 @@ struct vfdi_status;
* @tx_queue: TX DMA queues
* @rx_queue: RX DMA queues
* @channel: Channels
- * @channel_name: Names for channels and their IRQs
+ * @msi_context: Context for each MSI
* @extra_channel_types: Types of extra (non-traffic) channels that
* should be allocated for this NIC
* @rxq_entries: Size of receive queues requested by user.
@@ -709,6 +723,8 @@ struct vfdi_status;
* @rx_scatter: Scatter mode enabled for receives
* @int_error_count: Number of internal errors seen recently
* @int_error_expire: Time at which error count will be expired
+ * @irq_soft_enabled: Are IRQs soft-enabled? If not, IRQ handler will
+ * acknowledge but do nothing else.
* @irq_status: Interrupt status buffer
* @irq_zero_count: Number of legacy IRQs seen with queue flags == 0
* @irq_level: IRQ level/index for IRQs not triggered by an event queue
@@ -786,7 +802,6 @@ struct efx_nic {
unsigned int port_num;
const struct efx_nic_type *type;
int legacy_irq;
- bool legacy_irq_enabled;
bool eeh_disabled_legacy_irq;
struct workqueue_struct *workqueue;
char workqueue_name[16];
@@ -804,7 +819,7 @@ struct efx_nic {
unsigned long reset_pending;
struct efx_channel *channel[EFX_MAX_CHANNELS];
- char channel_name[EFX_MAX_CHANNELS][IFNAMSIZ + 6];
+ struct efx_msi_context msi_context[EFX_MAX_CHANNELS];
const struct efx_channel_type *
extra_channel_type[EFX_MAX_EXTRA_CHANNELS];
@@ -835,6 +850,7 @@ struct efx_nic {
unsigned int_error_count;
unsigned long int_error_expire;
+ bool irq_soft_enabled;
struct efx_buffer irq_status;
unsigned irq_zero_count;
unsigned irq_level;
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index f758333..c17d659 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -1567,6 +1567,7 @@ irqreturn_t efx_nic_fatal_interrupt(struct efx_nic *efx)
static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
{
struct efx_nic *efx = dev_id;
+ bool soft_enabled = ACCESS_ONCE(efx->irq_soft_enabled);
efx_oword_t *int_ker = efx->irq_status.addr;
irqreturn_t result = IRQ_NONE;
struct efx_channel *channel;
@@ -1574,12 +1575,6 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
u32 queues;
int syserr;
- /* Could this be ours? If interrupts are disabled then the
- * channel state may not be valid.
- */
- if (!efx->legacy_irq_enabled)
- return result;
-
/* Read the ISR which also ACKs the interrupts */
efx_readd(efx, ®, FR_BZ_INT_ISR0);
queues = EFX_EXTRACT_DWORD(reg, 0, 31);
@@ -1595,7 +1590,7 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
}
/* Handle non-event-queue sources */
- if (queues & (1U << efx->irq_level)) {
+ if (queues & (1U << efx->irq_level) && soft_enabled) {
syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
if (unlikely(syserr))
return efx_nic_fatal_interrupt(efx);
@@ -1607,10 +1602,12 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
efx->irq_zero_count = 0;
/* Schedule processing of any interrupting queues */
- efx_for_each_channel(channel, efx) {
- if (queues & 1)
- efx_schedule_channel_irq(channel);
- queues >>= 1;
+ if (likely(soft_enabled)) {
+ efx_for_each_channel(channel, efx) {
+ if (queues & 1)
+ efx_schedule_channel_irq(channel);
+ queues >>= 1;
+ }
}
result = IRQ_HANDLED;
@@ -1623,12 +1620,15 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
result = IRQ_HANDLED;
/* Ensure we schedule or rearm all event queues */
- efx_for_each_channel(channel, efx) {
- event = efx_event(channel, channel->eventq_read_ptr);
- if (efx_event_present(event))
- efx_schedule_channel_irq(channel);
- else
- efx_nic_eventq_read_ack(channel);
+ if (likely(soft_enabled)) {
+ efx_for_each_channel(channel, efx) {
+ event = efx_event(channel,
+ channel->eventq_read_ptr);
+ if (efx_event_present(event))
+ efx_schedule_channel_irq(channel);
+ else
+ efx_nic_eventq_read_ack(channel);
+ }
}
}
@@ -1649,8 +1649,8 @@ static irqreturn_t efx_legacy_interrupt(int irq, void *dev_id)
*/
static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
{
- struct efx_channel *channel = *(struct efx_channel **)dev_id;
- struct efx_nic *efx = channel->efx;
+ struct efx_msi_context *context = dev_id;
+ struct efx_nic *efx = context->efx;
efx_oword_t *int_ker = efx->irq_status.addr;
int syserr;
@@ -1658,8 +1658,11 @@ static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
"IRQ %d on CPU %d status " EFX_OWORD_FMT "\n",
irq, raw_smp_processor_id(), EFX_OWORD_VAL(*int_ker));
+ if (!likely(ACCESS_ONCE(efx->irq_soft_enabled)))
+ return IRQ_HANDLED;
+
/* Handle non-event-queue sources */
- if (channel->channel == efx->irq_level) {
+ if (context->index == efx->irq_level) {
syserr = EFX_OWORD_FIELD(*int_ker, FSF_AZ_NET_IVEC_FATAL_INT);
if (unlikely(syserr))
return efx_nic_fatal_interrupt(efx);
@@ -1667,7 +1670,7 @@ static irqreturn_t efx_msi_interrupt(int irq, void *dev_id)
}
/* Schedule processing of the channel */
- efx_schedule_channel_irq(channel);
+ efx_schedule_channel_irq(efx->channel[context->index]);
return IRQ_HANDLED;
}
@@ -1739,8 +1742,8 @@ int efx_nic_init_interrupt(struct efx_nic *efx)
efx_for_each_channel(channel, efx) {
rc = request_irq(channel->irq, efx_msi_interrupt,
IRQF_PROBE_SHARED, /* Not shared */
- efx->channel_name[channel->channel],
- &efx->channel[channel->channel]);
+ efx->msi_context[channel->channel].name,
+ &efx->msi_context[channel->channel]);
if (rc) {
netif_err(efx, drv, efx->net_dev,
"failed to hook IRQ %d\n", channel->irq);
@@ -1769,7 +1772,7 @@ int efx_nic_init_interrupt(struct efx_nic *efx)
efx_for_each_channel(channel, efx) {
if (n_irqs-- == 0)
break;
- free_irq(channel->irq, &efx->channel[channel->channel]);
+ free_irq(channel->irq, &efx->msi_context[channel->channel]);
}
fail1:
return rc;
@@ -1787,7 +1790,7 @@ void efx_nic_fini_interrupt(struct efx_nic *efx)
/* Disable MSI/MSI-X interrupts */
efx_for_each_channel(channel, efx)
- free_irq(channel->irq, &efx->channel[channel->channel]);
+ free_irq(channel->irq, &efx->msi_context[channel->channel]);
/* ACK legacy interrupt */
if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 05/16] sfc: Remove efx_process_channel_now()
From: Ben Hutchings @ 2013-08-25 23:02 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1377471363.2586.69.camel@deadeye.wl.decadent.org.uk>
efx_process_channel_now() is unneeded since self-tests can rely on
normal NAPI polling. Remove it and all calls to it.
efx_channel::work_pending and efx_channel_processed() are also
unneeded (the latter being the same as efx_nic_eventq_read_ack()).
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/efx.c | 69 +-------------------------------
drivers/net/ethernet/sfc/efx.h | 2 -
drivers/net/ethernet/sfc/net_driver.h | 2 -
drivers/net/ethernet/sfc/selftest.c | 11 -----
4 files changed, 3 insertions(+), 81 deletions(-)
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index c729688..2b2dba1 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -255,23 +255,6 @@ static int efx_process_channel(struct efx_channel *channel, int budget)
return spent;
}
-/* Mark channel as finished processing
- *
- * Note that since we will not receive further interrupts for this
- * channel before we finish processing and call the eventq_read_ack()
- * method, there is no need to use the interrupt hold-off timers.
- */
-static inline void efx_channel_processed(struct efx_channel *channel)
-{
- /* The interrupt handler for this channel may set work_pending
- * as soon as we acknowledge the events we've seen. Make sure
- * it's cleared before then. */
- channel->work_pending = false;
- smp_wmb();
-
- efx_nic_eventq_read_ack(channel);
-}
-
/* NAPI poll handler
*
* NAPI guarantees serialisation of polls of the same device, which
@@ -316,58 +299,16 @@ static int efx_poll(struct napi_struct *napi, int budget)
/* There is no race here; although napi_disable() will
* only wait for napi_complete(), this isn't a problem
- * since efx_channel_processed() will have no effect if
+ * since efx_nic_eventq_read_ack() will have no effect if
* interrupts have already been disabled.
*/
napi_complete(napi);
- efx_channel_processed(channel);
+ efx_nic_eventq_read_ack(channel);
}
return spent;
}
-/* Process the eventq of the specified channel immediately on this CPU
- *
- * Disable hardware generated interrupts, wait for any existing
- * processing to finish, then directly poll (and ack ) the eventq.
- * Finally reenable NAPI and interrupts.
- *
- * This is for use only during a loopback self-test. It must not
- * deliver any packets up the stack as this can result in deadlock.
- */
-void efx_process_channel_now(struct efx_channel *channel)
-{
- struct efx_nic *efx = channel->efx;
-
- BUG_ON(channel->channel >= efx->n_channels);
- BUG_ON(!channel->enabled);
- BUG_ON(!efx->loopback_selftest);
-
- /* Disable interrupts and wait for ISRs to complete */
- efx_nic_disable_interrupts(efx);
- if (efx->legacy_irq) {
- synchronize_irq(efx->legacy_irq);
- efx->legacy_irq_enabled = false;
- }
- if (channel->irq)
- synchronize_irq(channel->irq);
-
- /* Wait for any NAPI processing to complete */
- napi_disable(&channel->napi_str);
-
- /* Poll the channel */
- efx_process_channel(channel, channel->eventq_mask + 1);
-
- /* Ack the eventq. This may cause an interrupt to be generated
- * when they are reenabled */
- efx_channel_processed(channel);
-
- napi_enable(&channel->napi_str);
- if (efx->legacy_irq)
- efx->legacy_irq_enabled = true;
- efx_nic_enable_interrupts(efx);
-}
-
/* Create event queue
* Event queue memory allocations are done only once. If the channel
* is reset, the memory buffer will be reused; this guards against
@@ -407,11 +348,7 @@ static void efx_start_eventq(struct efx_channel *channel)
netif_dbg(channel->efx, ifup, channel->efx->net_dev,
"chan %d start event queue\n", channel->channel);
- /* The interrupt handler for this channel may set work_pending
- * as soon as we enable it. Make sure it's cleared before
- * then. Similarly, make sure it sees the enabled flag set.
- */
- channel->work_pending = false;
+ /* Make sure the NAPI handler sees the enabled flag set */
channel->enabled = true;
smp_wmb();
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h
index bdb30bb..09e633a 100644
--- a/drivers/net/ethernet/sfc/efx.h
+++ b/drivers/net/ethernet/sfc/efx.h
@@ -109,7 +109,6 @@ static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
/* Channels */
extern int efx_channel_dummy_op_int(struct efx_channel *channel);
extern void efx_channel_dummy_op_void(struct efx_channel *channel);
-extern void efx_process_channel_now(struct efx_channel *channel);
extern int
efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries);
@@ -155,7 +154,6 @@ static inline void efx_schedule_channel(struct efx_channel *channel)
netif_vdbg(channel->efx, intr, channel->efx->net_dev,
"channel %d scheduling NAPI poll on CPU%d\n",
channel->channel, raw_smp_processor_id());
- channel->work_pending = true;
napi_schedule(&channel->napi_str);
}
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index ea64cd8..ad89d7d 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -361,7 +361,6 @@ enum efx_rx_alloc_method {
* @irq_moderation: IRQ moderation value (in hardware ticks)
* @napi_dev: Net device used with NAPI
* @napi_str: NAPI control structure
- * @work_pending: Is work pending via NAPI?
* @eventq: Event queue buffer
* @eventq_mask: Event queue pointer mask
* @eventq_read_ptr: Event queue read pointer
@@ -393,7 +392,6 @@ struct efx_channel {
unsigned int irq_moderation;
struct net_device *napi_dev;
struct napi_struct napi_str;
- bool work_pending;
struct efx_special_buffer eventq;
unsigned int eventq_mask;
unsigned int eventq_read_ptr;
diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c
index 2069f51..716cff9 100644
--- a/drivers/net/ethernet/sfc/selftest.c
+++ b/drivers/net/ethernet/sfc/selftest.c
@@ -447,14 +447,7 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
static int efx_poll_loopback(struct efx_nic *efx)
{
struct efx_loopback_state *state = efx->loopback_selftest;
- struct efx_channel *channel;
- /* NAPI polling is not enabled, so process channels
- * synchronously */
- efx_for_each_channel(channel, efx) {
- if (channel->work_pending)
- efx_process_channel_now(channel);
- }
return atomic_read(&state->rx_good) == state->packet_count;
}
@@ -586,10 +579,6 @@ static int efx_wait_for_link(struct efx_nic *efx)
mutex_lock(&efx->mac_lock);
efx->type->monitor(efx);
mutex_unlock(&efx->mac_lock);
- } else {
- struct efx_channel *channel = efx_get_channel(efx, 0);
- if (channel->work_pending)
- efx_process_channel_now(channel);
}
mutex_lock(&efx->mac_lock);
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 04/16] sfc: Rename Falcon-architecture register definitions
From: Ben Hutchings @ 2013-08-25 23:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1377471363.2586.69.camel@deadeye.wl.decadent.org.uk>
The EF10 architecture has a very different register layout from
previous controllers, so we'll use separate files for the two sets of
register definitions. Use 'farch' as an abbreviation for
Falcon-architecture.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/falcon.c | 2 +-
drivers/net/ethernet/sfc/{regs.h => farch_regs.h} | 6 +++---
drivers/net/ethernet/sfc/filter.c | 2 +-
drivers/net/ethernet/sfc/mcdi.c | 2 +-
drivers/net/ethernet/sfc/nic.c | 2 +-
drivers/net/ethernet/sfc/ptp.c | 2 +-
drivers/net/ethernet/sfc/siena.c | 2 +-
drivers/net/ethernet/sfc/siena_sriov.c | 2 +-
8 files changed, 10 insertions(+), 10 deletions(-)
rename drivers/net/ethernet/sfc/{regs.h => farch_regs.h} (99%)
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 395d89d..f87710e 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -21,7 +21,7 @@
#include "efx.h"
#include "spi.h"
#include "nic.h"
-#include "regs.h"
+#include "farch_regs.h"
#include "io.h"
#include "phy.h"
#include "workarounds.h"
diff --git a/drivers/net/ethernet/sfc/regs.h b/drivers/net/ethernet/sfc/farch_regs.h
similarity index 99%
rename from drivers/net/ethernet/sfc/regs.h
rename to drivers/net/ethernet/sfc/farch_regs.h
index 27ad348d..00ef17a 100644
--- a/drivers/net/ethernet/sfc/regs.h
+++ b/drivers/net/ethernet/sfc/farch_regs.h
@@ -8,8 +8,8 @@
* by the Free Software Foundation, incorporated herein by reference.
*/
-#ifndef EFX_REGS_H
-#define EFX_REGS_H
+#ifndef EFX_FARCH_REGS_H
+#define EFX_FARCH_REGS_H
/*
* Falcon hardware architecture definitions have a name prefix following
@@ -2925,4 +2925,4 @@
#define FSF_AZ_DRV_GEN_EV_MAGIC_LBN 0
#define FSF_AZ_DRV_GEN_EV_MAGIC_WIDTH 32
-#endif /* EFX_REGS_H */
+#endif /* EFX_FARCH_REGS_H */
diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c
index 30d7442..fb01fdb 100644
--- a/drivers/net/ethernet/sfc/filter.c
+++ b/drivers/net/ethernet/sfc/filter.c
@@ -13,7 +13,7 @@
#include "filter.h"
#include "io.h"
#include "nic.h"
-#include "regs.h"
+#include "farch_regs.h"
/* "Fudge factors" - difference between programmed value and actual depth.
* Due to pipelined implementation we need to program H/W with a value that
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index d7d3a8a..dffadb2 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -11,7 +11,7 @@
#include "net_driver.h"
#include "nic.h"
#include "io.h"
-#include "regs.h"
+#include "farch_regs.h"
#include "mcdi_pcol.h"
#include "phy.h"
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 372891c..f758333 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -19,7 +19,7 @@
#include "bitfield.h"
#include "efx.h"
#include "nic.h"
-#include "regs.h"
+#include "farch_regs.h"
#include "io.h"
#include "workarounds.h"
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index 56a8b88..59e09e1 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -46,7 +46,7 @@
#include "mcdi.h"
#include "mcdi_pcol.h"
#include "io.h"
-#include "regs.h"
+#include "farch_regs.h"
#include "nic.h"
/* Maximum number of events expected to make up a PTP event */
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index f0ae262..d0eeb03 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -19,7 +19,7 @@
#include "efx.h"
#include "nic.h"
#include "spi.h"
-#include "regs.h"
+#include "farch_regs.h"
#include "io.h"
#include "phy.h"
#include "workarounds.h"
diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c
index 6258e7f..4d214bc 100644
--- a/drivers/net/ethernet/sfc/siena_sriov.c
+++ b/drivers/net/ethernet/sfc/siena_sriov.c
@@ -15,7 +15,7 @@
#include "mcdi.h"
#include "filter.h"
#include "mcdi_pcol.h"
-#include "regs.h"
+#include "farch_regs.h"
#include "vfdi.h"
/* Number of longs required to track all the VIs in a VF */
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 03/16] sfc: Make struct efx_special_buffer less special
From: Ben Hutchings @ 2013-08-25 23:01 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1377471363.2586.69.camel@deadeye.wl.decadent.org.uk>
On EF10, the firmware is in charge of allocating buffer table entries.
Change struct efx_special_buffer to use a struct efx_buffer member,
so that it can be used with efx_nic_{alloc,free}_buffer() in that
case.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/net_driver.h | 47 ++++++++++++++++-----------------
drivers/net/ethernet/sfc/nic.c | 33 ++++++++++-------------
2 files changed, 37 insertions(+), 43 deletions(-)
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index fb9361f..ea64cd8 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -93,21 +93,36 @@ struct efx_ptp_data;
struct efx_self_tests;
/**
- * struct efx_special_buffer - An Efx special buffer
- * @addr: CPU base address of the buffer
+ * struct efx_buffer - A general-purpose DMA buffer
+ * @addr: host base address of the buffer
* @dma_addr: DMA base address of the buffer
* @len: Buffer length, in bytes
- * @index: Buffer index within controller;s buffer table
- * @entries: Number of buffer table entries
*
- * Special buffers are used for the event queues and the TX and RX
- * descriptor queues for each channel. They are *not* used for the
- * actual transmit and receive buffers.
+ * The NIC uses these buffers for its interrupt status registers and
+ * MAC stats dumps.
*/
-struct efx_special_buffer {
+struct efx_buffer {
void *addr;
dma_addr_t dma_addr;
unsigned int len;
+};
+
+/**
+ * struct efx_special_buffer - DMA buffer entered into buffer table
+ * @buf: Standard &struct efx_buffer
+ * @index: Buffer index within controller;s buffer table
+ * @entries: Number of buffer table entries
+ *
+ * The NIC has a buffer table that maps buffers of size %EFX_BUF_SIZE.
+ * Event and descriptor rings are addressed via one or more buffer
+ * table entries (and so can be physically non-contiguous, although we
+ * currently do not take advantage of that). On Falcon and Siena we
+ * have to take care of allocating and initialising the entries
+ * ourselves. On later hardware this is managed by the firmware and
+ * @index and @entries are left as 0.
+ */
+struct efx_special_buffer {
+ struct efx_buffer buf;
unsigned int index;
unsigned int entries;
};
@@ -325,22 +340,6 @@ struct efx_rx_queue {
unsigned int slow_fill_count;
};
-/**
- * struct efx_buffer - An Efx general-purpose buffer
- * @addr: host base address of the buffer
- * @dma_addr: DMA base address of the buffer
- * @len: Buffer length, in bytes
- *
- * The NIC uses these buffers for its interrupt status registers and
- * MAC stats dumps.
- */
-struct efx_buffer {
- void *addr;
- dma_addr_t dma_addr;
- unsigned int len;
-};
-
-
enum efx_rx_alloc_method {
RX_ALLOC_METHOD_AUTO = 0,
RX_ALLOC_METHOD_SKB = 1,
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index efe2773..372891c 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -93,7 +93,7 @@ static inline void efx_write_buf_tbl(struct efx_nic *efx, efx_qword_t *value,
static inline efx_qword_t *efx_event(struct efx_channel *channel,
unsigned int index)
{
- return ((efx_qword_t *) (channel->eventq.addr)) +
+ return ((efx_qword_t *) (channel->eventq.buf.addr)) +
(index & channel->eventq_mask);
}
@@ -196,12 +196,12 @@ efx_init_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
dma_addr_t dma_addr;
int i;
- EFX_BUG_ON_PARANOID(!buffer->addr);
+ EFX_BUG_ON_PARANOID(!buffer->buf.addr);
/* Write buffer descriptors to NIC */
for (i = 0; i < buffer->entries; i++) {
index = buffer->index + i;
- dma_addr = buffer->dma_addr + (i * EFX_BUF_SIZE);
+ dma_addr = buffer->buf.dma_addr + (i * EFX_BUF_SIZE);
netif_dbg(efx, probe, efx->net_dev,
"mapping special buffer %d at %llx\n",
index, (unsigned long long)dma_addr);
@@ -250,13 +250,10 @@ static int efx_alloc_special_buffer(struct efx_nic *efx,
{
len = ALIGN(len, EFX_BUF_SIZE);
- buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
- &buffer->dma_addr, GFP_KERNEL);
- if (!buffer->addr)
+ if (efx_nic_alloc_buffer(efx, &buffer->buf, len, GFP_KERNEL))
return -ENOMEM;
- buffer->len = len;
buffer->entries = len / EFX_BUF_SIZE;
- BUG_ON(buffer->dma_addr & (EFX_BUF_SIZE - 1));
+ BUG_ON(buffer->buf.dma_addr & (EFX_BUF_SIZE - 1));
/* Select new buffer ID */
buffer->index = efx->next_buffer_table;
@@ -270,8 +267,8 @@ static int efx_alloc_special_buffer(struct efx_nic *efx,
"allocating special buffers %d-%d at %llx+%x "
"(virt %p phys %llx)\n", buffer->index,
buffer->index + buffer->entries - 1,
- (u64)buffer->dma_addr, len,
- buffer->addr, (u64)virt_to_phys(buffer->addr));
+ (u64)buffer->buf.dma_addr, len,
+ buffer->buf.addr, (u64)virt_to_phys(buffer->buf.addr));
return 0;
}
@@ -279,19 +276,17 @@ static int efx_alloc_special_buffer(struct efx_nic *efx,
static void
efx_free_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
{
- if (!buffer->addr)
+ if (!buffer->buf.addr)
return;
netif_dbg(efx, hw, efx->net_dev,
"deallocating special buffers %d-%d at %llx+%x "
"(virt %p phys %llx)\n", buffer->index,
buffer->index + buffer->entries - 1,
- (u64)buffer->dma_addr, buffer->len,
- buffer->addr, (u64)virt_to_phys(buffer->addr));
+ (u64)buffer->buf.dma_addr, buffer->buf.len,
+ buffer->buf.addr, (u64)virt_to_phys(buffer->buf.addr));
- dma_free_coherent(&efx->pci_dev->dev, buffer->len, buffer->addr,
- buffer->dma_addr);
- buffer->addr = NULL;
+ efx_nic_free_buffer(efx, &buffer->buf);
buffer->entries = 0;
}
@@ -335,7 +330,7 @@ void efx_nic_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer)
static inline efx_qword_t *
efx_tx_desc(struct efx_tx_queue *tx_queue, unsigned int index)
{
- return ((efx_qword_t *) (tx_queue->txd.addr)) + index;
+ return ((efx_qword_t *) (tx_queue->txd.buf.addr)) + index;
}
/* This writes to the TX_DESC_WPTR; write pointer for TX descriptor ring */
@@ -534,7 +529,7 @@ void efx_nic_remove_tx(struct efx_tx_queue *tx_queue)
static inline efx_qword_t *
efx_rx_desc(struct efx_rx_queue *rx_queue, unsigned int index)
{
- return ((efx_qword_t *) (rx_queue->rxd.addr)) + index;
+ return ((efx_qword_t *) (rx_queue->rxd.buf.addr)) + index;
}
/* This creates an entry in the RX descriptor queue */
@@ -1415,7 +1410,7 @@ void efx_nic_init_eventq(struct efx_channel *channel)
efx_init_special_buffer(efx, &channel->eventq);
/* Fill event queue with all ones (i.e. empty events) */
- memset(channel->eventq.addr, 0xff, channel->eventq.len);
+ memset(channel->eventq.buf.addr, 0xff, channel->eventq.buf.len);
/* Push event queue to card */
EFX_POPULATE_OWORD_3(reg,
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 02/16] sfc: Add GFP flags to efx_nic_alloc_buffer() and make most callers allow blocking
From: Ben Hutchings @ 2013-08-25 23:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1377471363.2586.69.camel@deadeye.wl.decadent.org.uk>
Most call sites for efx_nic_alloc_buffer() are part of the probe or
reconfiguration paths and can allocate with GFP_KERNEL. A few others
should use GFP_NOIO (I think). Only one is in atomic context and
must use the current GFP_ATOMIC.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/falcon.c | 5 +++--
drivers/net/ethernet/sfc/mcdi_mon.c | 2 +-
drivers/net/ethernet/sfc/mcdi_port.c | 2 +-
drivers/net/ethernet/sfc/nic.c | 4 ++--
drivers/net/ethernet/sfc/nic.h | 2 +-
drivers/net/ethernet/sfc/ptp.c | 2 +-
drivers/net/ethernet/sfc/siena.c | 3 ++-
drivers/net/ethernet/sfc/siena_sriov.c | 10 ++++++----
drivers/net/ethernet/sfc/tx.c | 3 ++-
9 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 522850036..395d89d 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -1418,7 +1418,7 @@ static int falcon_probe_port(struct efx_nic *efx)
/* Allocate buffer for stats */
rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
- FALCON_MAC_STATS_SIZE);
+ FALCON_MAC_STATS_SIZE, GFP_KERNEL);
if (rc)
return rc;
netif_dbg(efx, probe, efx->net_dev,
@@ -2035,7 +2035,8 @@ static int falcon_probe_nic(struct efx_nic *efx)
}
/* Allocate memory for INT_KER */
- rc = efx_nic_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t));
+ rc = efx_nic_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t),
+ GFP_KERNEL);
if (rc)
goto fail4;
BUG_ON(efx->irq_status.dma_addr & 0x0f);
diff --git a/drivers/net/ethernet/sfc/mcdi_mon.c b/drivers/net/ethernet/sfc/mcdi_mon.c
index 3179b2b..958c73f 100644
--- a/drivers/net/ethernet/sfc/mcdi_mon.c
+++ b/drivers/net/ethernet/sfc/mcdi_mon.c
@@ -261,7 +261,7 @@ int efx_mcdi_mon_probe(struct efx_nic *efx)
return -EIO;
rc = efx_nic_alloc_buffer(efx, &hwmon->dma_buf,
- 4 * MC_CMD_SENSOR_ENTRY_MAXNUM);
+ 4 * MC_CMD_SENSOR_ENTRY_MAXNUM, GFP_KERNEL);
if (rc)
return rc;
diff --git a/drivers/net/ethernet/sfc/mcdi_port.c b/drivers/net/ethernet/sfc/mcdi_port.c
index 8f31e3d..91df43f 100644
--- a/drivers/net/ethernet/sfc/mcdi_port.c
+++ b/drivers/net/ethernet/sfc/mcdi_port.c
@@ -989,7 +989,7 @@ int efx_mcdi_port_probe(struct efx_nic *efx)
/* Allocate buffer for stats */
rc = efx_nic_alloc_buffer(efx, &efx->stats_buffer,
- MC_CMD_MAC_NSTATS * sizeof(u64));
+ MC_CMD_MAC_NSTATS * sizeof(u64), GFP_KERNEL);
if (rc)
return rc;
netif_dbg(efx, probe, efx->net_dev,
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c
index 56ed3bc..efe2773 100644
--- a/drivers/net/ethernet/sfc/nic.c
+++ b/drivers/net/ethernet/sfc/nic.c
@@ -303,11 +303,11 @@ efx_free_special_buffer(struct efx_nic *efx, struct efx_special_buffer *buffer)
**************************************************************************/
int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
- unsigned int len)
+ unsigned int len, gfp_t gfp_flags)
{
buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
&buffer->dma_addr,
- GFP_ATOMIC | __GFP_ZERO);
+ gfp_flags | __GFP_ZERO);
if (!buffer->addr)
return -ENOMEM;
buffer->len = len;
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index c699203..9120e8b 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -332,7 +332,7 @@ extern void efx_nic_init_common(struct efx_nic *efx);
extern void efx_nic_push_rx_indir_table(struct efx_nic *efx);
int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
- unsigned int len);
+ unsigned int len, gfp_t gfp_flags);
void efx_nic_free_buffer(struct efx_nic *efx, struct efx_buffer *buffer);
/* Tests */
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index d96bfc4..56a8b88 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -875,7 +875,7 @@ static int efx_ptp_probe_channel(struct efx_channel *channel)
if (!efx->ptp_data)
return -ENOMEM;
- rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int));
+ rc = efx_nic_alloc_buffer(efx, &ptp->start, sizeof(int), GFP_KERNEL);
if (rc != 0)
goto fail1;
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 73b511a..f0ae262 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -237,7 +237,8 @@ static int siena_probe_nic(struct efx_nic *efx)
siena_init_wol(efx);
/* Allocate memory for INT_KER */
- rc = efx_nic_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t));
+ rc = efx_nic_alloc_buffer(efx, &efx->irq_status, sizeof(efx_oword_t),
+ GFP_KERNEL);
if (rc)
goto fail4;
BUG_ON(efx->irq_status.dma_addr & 0x0f);
diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c
index 2587d30..6258e7f 100644
--- a/drivers/net/ethernet/sfc/siena_sriov.c
+++ b/drivers/net/ethernet/sfc/siena_sriov.c
@@ -997,7 +997,7 @@ static void efx_sriov_reset_vf_work(struct work_struct *work)
struct efx_nic *efx = vf->efx;
struct efx_buffer buf;
- if (!efx_nic_alloc_buffer(efx, &buf, EFX_PAGE_SIZE)) {
+ if (!efx_nic_alloc_buffer(efx, &buf, EFX_PAGE_SIZE, GFP_NOIO)) {
efx_sriov_reset_vf(vf, &buf);
efx_nic_free_buffer(efx, &buf);
}
@@ -1241,7 +1241,8 @@ static int efx_sriov_vfs_init(struct efx_nic *efx)
pci_domain_nr(pci_dev->bus), pci_dev->bus->number,
PCI_SLOT(devfn), PCI_FUNC(devfn));
- rc = efx_nic_alloc_buffer(efx, &vf->buf, EFX_PAGE_SIZE);
+ rc = efx_nic_alloc_buffer(efx, &vf->buf, EFX_PAGE_SIZE,
+ GFP_KERNEL);
if (rc)
goto fail;
@@ -1273,7 +1274,8 @@ int efx_sriov_init(struct efx_nic *efx)
if (rc)
goto fail_cmd;
- rc = efx_nic_alloc_buffer(efx, &efx->vfdi_status, sizeof(*vfdi_status));
+ rc = efx_nic_alloc_buffer(efx, &efx->vfdi_status, sizeof(*vfdi_status),
+ GFP_KERNEL);
if (rc)
goto fail_status;
vfdi_status = efx->vfdi_status.addr;
@@ -1528,7 +1530,7 @@ void efx_sriov_reset(struct efx_nic *efx)
efx_sriov_usrev(efx, true);
(void)efx_sriov_cmd(efx, true, NULL, NULL);
- if (efx_nic_alloc_buffer(efx, &buf, EFX_PAGE_SIZE))
+ if (efx_nic_alloc_buffer(efx, &buf, EFX_PAGE_SIZE, GFP_NOIO))
return;
for (vf_i = 0; vf_i < efx->vf_init_count; ++vf_i) {
diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c
index 5e090e5..c0d4040 100644
--- a/drivers/net/ethernet/sfc/tx.c
+++ b/drivers/net/ethernet/sfc/tx.c
@@ -708,7 +708,8 @@ static u8 *efx_tsoh_get_buffer(struct efx_tx_queue *tx_queue,
TSOH_STD_SIZE * (index % TSOH_PER_PAGE) + TSOH_OFFSET;
if (unlikely(!page_buf->addr) &&
- efx_nic_alloc_buffer(tx_queue->efx, page_buf, PAGE_SIZE))
+ efx_nic_alloc_buffer(tx_queue->efx, page_buf, PAGE_SIZE,
+ GFP_ATOMIC))
return NULL;
result = (u8 *)page_buf->addr + offset;
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* [PATCH net-next 01/16] sfc: Make MCDI independent of Siena
From: Ben Hutchings @ 2013-08-25 23:00 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
In-Reply-To: <1377471363.2586.69.camel@deadeye.wl.decadent.org.uk>
Move the lowest layer (transport) of the current MCDI code to
per-NIC-type operations.
Introduce a new structure and efx_nic member for MCDI-specific data.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/ethernet/sfc/mcdi.c | 87 +++++++++----------------------
drivers/net/ethernet/sfc/mcdi.h | 21 ++++++++
drivers/net/ethernet/sfc/net_driver.h | 20 +++++++
drivers/net/ethernet/sfc/nic.h | 16 ------
drivers/net/ethernet/sfc/siena.c | 90 +++++++++++++++++++++++++++++++++
5 files changed, 157 insertions(+), 77 deletions(-)
diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c
index 2b9ef28..d7d3a8a 100644
--- a/drivers/net/ethernet/sfc/mcdi.c
+++ b/drivers/net/ethernet/sfc/mcdi.c
@@ -24,13 +24,6 @@
#define MCDI_RPC_TIMEOUT (10 * HZ)
-#define MCDI_PDU(efx) \
- (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST)
-#define MCDI_DOORBELL(efx) \
- (efx_port_num(efx) ? MC_SMEM_P1_DOORBELL_OFST : MC_SMEM_P0_DOORBELL_OFST)
-#define MCDI_STATUS(efx) \
- (efx_port_num(efx) ? MC_SMEM_P1_STATUS_OFST : MC_SMEM_P0_STATUS_OFST)
-
/* A reboot/assertion causes the MCDI status word to be set after the
* command word is set or a REBOOT event is sent. If we notice a reboot
* via these mechanisms then wait 10ms for the status word to be set. */
@@ -44,16 +37,18 @@
static inline struct efx_mcdi_iface *efx_mcdi(struct efx_nic *efx)
{
- struct siena_nic_data *nic_data;
- EFX_BUG_ON_PARANOID(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
- nic_data = efx->nic_data;
- return &nic_data->mcdi;
+ EFX_BUG_ON_PARANOID(!efx->mcdi);
+ return &efx->mcdi->iface;
}
int efx_mcdi_init(struct efx_nic *efx)
{
struct efx_mcdi_iface *mcdi;
+ efx->mcdi = kzalloc(sizeof(*efx->mcdi), GFP_KERNEL);
+ if (!efx->mcdi)
+ return -ENOMEM;
+
mcdi = efx_mcdi(efx);
init_waitqueue_head(&mcdi->wq);
spin_lock_init(&mcdi->iface_lock);
@@ -66,16 +61,19 @@ int efx_mcdi_init(struct efx_nic *efx)
return efx_mcdi_handle_assertion(efx);
}
+void efx_mcdi_fini(struct efx_nic *efx)
+{
+ BUG_ON(efx->mcdi &&
+ atomic_read(&efx->mcdi->iface.state) != MCDI_STATE_QUIESCENT);
+ kfree(efx->mcdi);
+}
+
static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
const efx_dword_t *inbuf, size_t inlen)
{
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
- unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
- unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx);
- unsigned int i;
efx_dword_t hdr;
u32 xflags, seqno;
- unsigned int inlen_dw = DIV_ROUND_UP(inlen, 4);
BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
BUG_ON(inlen > MCDI_CTL_SDU_LEN_MAX_V1);
@@ -93,31 +91,18 @@ static void efx_mcdi_copyin(struct efx_nic *efx, unsigned cmd,
MCDI_HEADER_SEQ, seqno,
MCDI_HEADER_XFLAGS, xflags);
- efx_writed(efx, &hdr, pdu);
-
- for (i = 0; i < inlen_dw; i++)
- efx_writed(efx, &inbuf[i], pdu + 4 + 4 * i);
-
- /* Ensure the payload is written out before the header */
- wmb();
-
- /* ring the doorbell with a distinctive value */
- _efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
+ efx->type->mcdi_request(efx, &hdr, 4, inbuf, inlen);
}
static void
efx_mcdi_copyout(struct efx_nic *efx, efx_dword_t *outbuf, size_t outlen)
{
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
- unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
- unsigned int outlen_dw = DIV_ROUND_UP(outlen, 4);
- int i;
BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
BUG_ON(outlen > MCDI_CTL_SDU_LEN_MAX_V1);
- for (i = 0; i < outlen_dw; i++)
- efx_readd(efx, &outbuf[i], pdu + 4 + 4 * i);
+ efx->type->mcdi_read_response(efx, outbuf, 4, outlen);
}
static int efx_mcdi_poll(struct efx_nic *efx)
@@ -125,7 +110,6 @@ static int efx_mcdi_poll(struct efx_nic *efx)
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
unsigned long time, finish;
unsigned int respseq, respcmd, error;
- unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
unsigned int rc, spins;
efx_dword_t reg;
@@ -152,19 +136,14 @@ static int efx_mcdi_poll(struct efx_nic *efx)
time = jiffies;
rmb();
- efx_readd(efx, ®, pdu);
-
- /* All 1's indicates that shared memory is in reset (and is
- * not a valid header). Wait for it to come out reset before
- * completing the command */
- if (EFX_DWORD_FIELD(reg, EFX_DWORD_0) != 0xffffffff &&
- EFX_DWORD_FIELD(reg, MCDI_HEADER_RESPONSE))
+ if (efx->type->mcdi_poll_response(efx))
break;
if (time_after(time, finish))
return -ETIMEDOUT;
}
+ efx->type->mcdi_read_response(efx, ®, 0, 4);
mcdi->resplen = EFX_DWORD_FIELD(reg, MCDI_HEADER_DATALEN);
respseq = EFX_DWORD_FIELD(reg, MCDI_HEADER_SEQ);
respcmd = EFX_DWORD_FIELD(reg, MCDI_HEADER_CODE);
@@ -179,7 +158,7 @@ static int efx_mcdi_poll(struct efx_nic *efx)
respseq, mcdi->seqno);
rc = EIO;
} else if (error) {
- efx_readd(efx, ®, pdu + 4);
+ efx->type->mcdi_read_response(efx, ®, 4, 4);
switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) {
#define TRANSLATE_ERROR(name) \
case MC_CMD_ERR_ ## name: \
@@ -215,17 +194,13 @@ out:
*/
int efx_mcdi_poll_reboot(struct efx_nic *efx)
{
- unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx);
- efx_dword_t reg;
- uint32_t value;
-
- if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
- return false;
+ int rc;
- efx_readd(efx, ®, addr);
- value = EFX_DWORD_FIELD(reg, EFX_DWORD_0);
+ if (!efx->mcdi)
+ return 0;
- if (value == 0)
+ rc = efx->type->mcdi_poll_reboot(efx);
+ if (!rc)
return 0;
/* MAC statistics have been cleared on the NIC; clear our copy
@@ -233,13 +208,7 @@ int efx_mcdi_poll_reboot(struct efx_nic *efx)
*/
memset(&efx->mac_stats, 0, sizeof(efx->mac_stats));
- EFX_ZERO_DWORD(reg);
- efx_writed(efx, ®, addr);
-
- if (value == MC_STATUS_DWORD_ASSERT)
- return -EINTR;
- else
- return -EIO;
+ return rc;
}
static void efx_mcdi_acquire(struct efx_mcdi_iface *mcdi)
@@ -345,8 +314,6 @@ void efx_mcdi_rpc_start(struct efx_nic *efx, unsigned cmd,
{
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
- BUG_ON(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
-
efx_mcdi_acquire(mcdi);
/* Serialise with efx_mcdi_ev_cpl() and efx_mcdi_ev_death() */
@@ -364,8 +331,6 @@ int efx_mcdi_rpc_finish(struct efx_nic *efx, unsigned cmd, size_t inlen,
struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
int rc;
- BUG_ON(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
-
if (mcdi->mode == MCDI_MODE_POLL)
rc = efx_mcdi_poll(efx);
else
@@ -426,7 +391,7 @@ void efx_mcdi_mode_poll(struct efx_nic *efx)
{
struct efx_mcdi_iface *mcdi;
- if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
+ if (!efx->mcdi)
return;
mcdi = efx_mcdi(efx);
@@ -450,7 +415,7 @@ void efx_mcdi_mode_event(struct efx_nic *efx)
{
struct efx_mcdi_iface *mcdi;
- if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
+ if (!efx->mcdi)
return;
mcdi = efx_mcdi(efx);
diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h
index 6c58dbd..0bfed2a 100644
--- a/drivers/net/ethernet/sfc/mcdi.h
+++ b/drivers/net/ethernet/sfc/mcdi.h
@@ -65,7 +65,28 @@ struct efx_mcdi_mon {
unsigned int n_attrs;
};
+/**
+ * struct efx_mcdi_data - extra state for NICs that implement MCDI
+ * @iface: Interface/protocol state
+ * @hwmon: Hardware monitor state
+ */
+struct efx_mcdi_data {
+ struct efx_mcdi_iface iface;
+#ifdef CONFIG_SFC_MCDI_MON
+ struct efx_mcdi_mon hwmon;
+#endif
+};
+
+#ifdef CONFIG_SFC_MCDI_MON
+static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
+{
+ EFX_BUG_ON_PARANOID(!efx->mcdi);
+ return &efx->mcdi->hwmon;
+}
+#endif
+
extern int efx_mcdi_init(struct efx_nic *efx);
+extern void efx_mcdi_fini(struct efx_nic *efx);
extern int efx_mcdi_rpc(struct efx_nic *efx, unsigned cmd,
const efx_dword_t *inbuf, size_t inlen,
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index bdded38..fb9361f 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -718,6 +718,7 @@ struct vfdi_status;
* @selftest_work: Work item for asynchronous self-test
* @mtd_list: List of MTDs attached to the NIC
* @nic_data: Hardware dependent state
+ * @mcdi: Management-Controller-to-Driver Interface state
* @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
* efx_monitor() and efx_reconfigure_port()
* @port_enabled: Port enabled indicator.
@@ -847,6 +848,7 @@ struct efx_nic {
#endif
void *nic_data;
+ struct efx_mcdi_data *mcdi;
struct mutex mac_lock;
struct work_struct mac_work;
@@ -956,6 +958,17 @@ static inline unsigned int efx_port_num(struct efx_nic *efx)
* @test_chip: Test registers. Should use efx_nic_test_registers(), and is
* expected to reset the NIC.
* @test_nvram: Test validity of NVRAM contents
+ * @mcdi_request: Send an MCDI request with the given header and SDU.
+ * The SDU length may be any value from 0 up to the protocol-
+ * defined maximum, but its buffer will be padded to a multiple
+ * of 4 bytes.
+ * @mcdi_poll_response: Test whether an MCDI response is available.
+ * @mcdi_read_response: Read the MCDI response PDU. The offset will
+ * be a multiple of 4. The length may not be, but the buffer
+ * will be padded so it is safe to round up.
+ * @mcdi_poll_reboot: Test whether the MCDI has rebooted. If so,
+ * return an appropriate error code for aborting any current
+ * request; otherwise return 0.
* @revision: Hardware architecture revision
* @mem_map_size: Memory BAR mapped size
* @txd_ptr_tbl_base: TX descriptor ring base address
@@ -1004,6 +1017,13 @@ struct efx_nic_type {
void (*resume_wol)(struct efx_nic *efx);
int (*test_chip)(struct efx_nic *efx, struct efx_self_tests *tests);
int (*test_nvram)(struct efx_nic *efx);
+ void (*mcdi_request)(struct efx_nic *efx,
+ const efx_dword_t *hdr, size_t hdr_len,
+ const efx_dword_t *sdu, size_t sdu_len);
+ bool (*mcdi_poll_response)(struct efx_nic *efx);
+ void (*mcdi_read_response)(struct efx_nic *efx, efx_dword_t *pdu,
+ size_t pdu_offset, size_t pdu_len);
+ int (*mcdi_poll_reboot)(struct efx_nic *efx);
int revision;
unsigned int mem_map_size;
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index 0d38cc2..c699203 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -140,28 +140,12 @@ static inline struct falcon_board *falcon_board(struct efx_nic *efx)
/**
* struct siena_nic_data - Siena NIC state
- * @mcdi: Management-Controller-to-Driver Interface
* @wol_filter_id: Wake-on-LAN packet filter id
- * @hwmon: Hardware monitor state
*/
struct siena_nic_data {
- struct efx_mcdi_iface mcdi;
int wol_filter_id;
-#ifdef CONFIG_SFC_MCDI_MON
- struct efx_mcdi_mon hwmon;
-#endif
};
-#ifdef CONFIG_SFC_MCDI_MON
-static inline struct efx_mcdi_mon *efx_mcdi_mon(struct efx_nic *efx)
-{
- struct siena_nic_data *nic_data;
- EFX_BUG_ON_PARANOID(efx_nic_rev(efx) < EFX_REV_SIENA_A0);
- nic_data = efx->nic_data;
- return &nic_data->hwmon;
-}
-#endif
-
/*
* On the SFC9000 family each port is associated with 1 PCI physical
* function (PF) handled by sfc and a configurable number of virtual
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 3dca771..73b511a 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -274,6 +274,7 @@ fail4:
fail3:
efx_mcdi_drv_attach(efx, false, NULL);
fail2:
+ efx_mcdi_fini(efx);
fail1:
kfree(efx->nic_data);
return rc;
@@ -367,6 +368,8 @@ static void siena_remove_nic(struct efx_nic *efx)
/* Tear down the private nic state */
kfree(efx->nic_data);
efx->nic_data = NULL;
+
+ efx_mcdi_fini(efx);
}
static int siena_try_update_nic_stats(struct efx_nic *efx)
@@ -574,6 +577,89 @@ static void siena_init_wol(struct efx_nic *efx)
}
}
+/**************************************************************************
+ *
+ * MCDI
+ *
+ **************************************************************************
+ */
+
+#define MCDI_PDU(efx) \
+ (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST)
+#define MCDI_DOORBELL(efx) \
+ (efx_port_num(efx) ? MC_SMEM_P1_DOORBELL_OFST : MC_SMEM_P0_DOORBELL_OFST)
+#define MCDI_STATUS(efx) \
+ (efx_port_num(efx) ? MC_SMEM_P1_STATUS_OFST : MC_SMEM_P0_STATUS_OFST)
+
+static void siena_mcdi_request(struct efx_nic *efx,
+ const efx_dword_t *hdr, size_t hdr_len,
+ const efx_dword_t *sdu, size_t sdu_len)
+{
+ unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+ unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx);
+ unsigned int i;
+ unsigned int inlen_dw = DIV_ROUND_UP(sdu_len, 4);
+
+ EFX_BUG_ON_PARANOID(hdr_len != 4);
+
+ efx_writed(efx, hdr, pdu);
+
+ for (i = 0; i < inlen_dw; i++)
+ efx_writed(efx, &sdu[i], pdu + hdr_len + 4 * i);
+
+ /* Ensure the request is written out before the doorbell */
+ wmb();
+
+ /* ring the doorbell with a distinctive value */
+ _efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
+}
+
+static bool siena_mcdi_poll_response(struct efx_nic *efx)
+{
+ unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+ efx_dword_t hdr;
+
+ efx_readd(efx, &hdr, pdu);
+
+ /* All 1's indicates that shared memory is in reset (and is
+ * not a valid hdr). Wait for it to come out reset before
+ * completing the command
+ */
+ return EFX_DWORD_FIELD(hdr, EFX_DWORD_0) != 0xffffffff &&
+ EFX_DWORD_FIELD(hdr, MCDI_HEADER_RESPONSE);
+}
+
+static void siena_mcdi_read_response(struct efx_nic *efx, efx_dword_t *outbuf,
+ size_t offset, size_t outlen)
+{
+ unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+ unsigned int outlen_dw = DIV_ROUND_UP(outlen, 4);
+ int i;
+
+ for (i = 0; i < outlen_dw; i++)
+ efx_readd(efx, &outbuf[i], pdu + offset + 4 * i);
+}
+
+static int siena_mcdi_poll_reboot(struct efx_nic *efx)
+{
+ unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_STATUS(efx);
+ efx_dword_t reg;
+ u32 value;
+
+ efx_readd(efx, ®, addr);
+ value = EFX_DWORD_FIELD(reg, EFX_DWORD_0);
+
+ if (value == 0)
+ return 0;
+
+ EFX_ZERO_DWORD(reg);
+ efx_writed(efx, ®, addr);
+
+ if (value == MC_STATUS_DWORD_ASSERT)
+ return -EINTR;
+ else
+ return -EIO;
+}
/**************************************************************************
*
@@ -613,6 +699,10 @@ const struct efx_nic_type siena_a0_nic_type = {
.resume_wol = siena_init_wol,
.test_chip = siena_test_chip,
.test_nvram = efx_mcdi_nvram_test_all,
+ .mcdi_request = siena_mcdi_request,
+ .mcdi_poll_response = siena_mcdi_poll_response,
+ .mcdi_read_response = siena_mcdi_read_response,
+ .mcdi_poll_reboot = siena_mcdi_poll_reboot,
.revision = EFX_REV_SIENA_A0,
.mem_map_size = (FR_CZ_MC_TREG_SMEM +
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply related
* Pull request: sfc-next 2013-08-25
From: Ben Hutchings @ 2013-08-25 22:56 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
[-- Attachment #1: Type: text/plain, Size: 3392 bytes --]
The following changes since commit f073dde03b3e8d11050d82f52caaf75fd924e069:
sfc: Make efx_mcdi_init() call efx_mcdi_handle_assertion() (2013-08-21 19:43:09 +0100)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bwh/sfc-next.git for-davem
for you to fetch changes up to f76fe120d81c96fa2a17ae41f0647c963dbb43cd:
sfc: Update and improve kernel-doc for efx_mcdi_state & efx_mcdi_iface (2013-08-21 20:20:41 +0100)
1. Refactoring and cleanup in preparation for new hardware support.
2. Some bug fixes for firmware completion handling. (They're not known
to cause real problems, otherwise I'd be submitting these for net and
stable.)
3. Update to the firmware protocol (MCDI) definitions.
Ben.
Ben Hutchings (16):
sfc: Make MCDI independent of Siena
sfc: Add GFP flags to efx_nic_alloc_buffer() and make most callers allow blocking
sfc: Make struct efx_special_buffer less special
sfc: Rename Falcon-architecture register definitions
sfc: Remove efx_process_channel_now()
sfc: Rework IRQ enable/disable
sfc: Limit scope of a Falcon A1 IRQ workaround
sfc: Stop RX refill before flushing RX queues
sfc: Remove bogus call to efx_release_tx_buffers()
sfc: Refactor queue teardown sequence to allow for EF10 flush behaviour
sfc: Move and rename Falcon/Siena common NIC operations
sfc: Translate MCDI error numbers received in events
sfc: Update MCDI protocol definitions for EF10
sfc: Add support for MCDI v2
sfc: Fix race in completion handling
sfc: Update and improve kernel-doc for efx_mcdi_state & efx_mcdi_iface
drivers/net/ethernet/sfc/Makefile | 3 +-
drivers/net/ethernet/sfc/efx.c | 216 +-
drivers/net/ethernet/sfc/efx.h | 3 -
drivers/net/ethernet/sfc/falcon.c | 76 +-
drivers/net/ethernet/sfc/farch.c | 1781 +++++++
drivers/net/ethernet/sfc/{regs.h => farch_regs.h} | 6 +-
drivers/net/ethernet/sfc/filter.c | 2 +-
drivers/net/ethernet/sfc/mcdi.c | 299 +-
drivers/net/ethernet/sfc/mcdi.h | 55 +-
drivers/net/ethernet/sfc/mcdi_mon.c | 2 +-
drivers/net/ethernet/sfc/mcdi_pcol.h | 5534 +++++++++++++++++++--
drivers/net/ethernet/sfc/mcdi_port.c | 5 +-
drivers/net/ethernet/sfc/net_driver.h | 155 +-
drivers/net/ethernet/sfc/nic.c | 1812 +-------
drivers/net/ethernet/sfc/nic.h | 219 +-
drivers/net/ethernet/sfc/ptp.c | 9 +-
drivers/net/ethernet/sfc/rx.c | 9 +-
drivers/net/ethernet/sfc/selftest.c | 11 -
drivers/net/ethernet/sfc/siena.c | 131 +-
drivers/net/ethernet/sfc/siena_sriov.c | 17 +-
drivers/net/ethernet/sfc/tx.c | 24 +-
21 files changed, 7788 insertions(+), 2581 deletions(-)
create mode 100644 drivers/net/ethernet/sfc/farch.c
rename drivers/net/ethernet/sfc/{regs.h => farch_regs.h} (99%)
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 482 bytes --]
^ permalink raw reply
* Re: [patch -next] ipip: potential race in ip_tunnel_init_net()
From: David Miller @ 2013-08-25 22:40 UTC (permalink / raw)
To: dan.carpenter
Cc: kuznet, jmorris, yoshfuji, kaber, netdev, kernel-janitors,
eric.dumazet
In-Reply-To: <20130823081537.GB31293@elgon.mountain>
From: Dan Carpenter <dan.carpenter@oracle.com>
Date: Fri, 23 Aug 2013 11:15:37 +0300
> Eric Dumazet says that my previous fix for an ERR_PTR dereference
> (ea857f28ab 'ipip: dereferencing an ERR_PTR in ip_tunnel_init_net()')
> could be racy and suggests the following fix instead.
>
> Reported-by: Eric Dumazet <eric.dumazet@gmail.com>
> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Applied, thanks Dan.
^ permalink raw reply
* Re: [PATCH -next] bonding: fix error return code in bond_enslave()
From: David Miller @ 2013-08-25 22:38 UTC (permalink / raw)
To: nikolay; +Cc: weiyj.lk, fubar, andy, yongjun_wei, netdev
In-Reply-To: <52176720.60300@redhat.com>
From: Nikolay Aleksandrov <nikolay@redhat.com>
Date: Fri, 23 Aug 2013 15:44:00 +0200
> On 08/23/2013 04:45 AM, Wei Yongjun wrote:
>> From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
>>
>> Fix to return a negative error code in the add bond vlan ids error
>> handling case instead of 0, as done elsewhere in this function.
>>
>> Introduced by commit 1ff412ad7714f6952f76ffd77f0a7f2f563288a1.
>> (bonding: change the bond's vlan syncing functions with the standard ones)
>>
>> Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
>
> Oops, missed the error code. Thanks :-)
>
> Acked-by: Nikolay Aleksandrov <nikolay@redhat.com>
Applied.
^ permalink raw reply
* sfc net-next
From: David Miller @ 2013-08-25 22:37 UTC (permalink / raw)
To: bhutchings; +Cc: netdev
Just FYI, I pulled your series in, thanks Ben.
^ permalink raw reply
* Re: [PATCH net-next] tcp: TSO packets automatic sizing
From: Yuchung Cheng @ 2013-08-25 22:01 UTC (permalink / raw)
To: Eric Dumazet
Cc: Neal Cardwell, David Miller, netdev, Van Jacobson, Tom Herbert
In-Reply-To: <1377370594.8828.72.camel@edumazet-glaptop>
On Sat, Aug 24, 2013 at 11:56 AM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
>
> On Fri, 2013-08-23 at 23:17 -0400, Neal Cardwell wrote:
>
> > I love this! Can't wait to play with it.
> >
>
> Totally agree ;)
>
> > Rather than implicitly initializing sk_pacing_rate to 0, I'd suggest
> > maybe initializing sk_pacing_rate to a value just high enough
> > (TCP_INIT_CWND * mss / 1ms?) so that in the first transmit the
> > connection can (as it does today) construct a single TSO jumbogram of
> > TCP_INIT_CWND segments and send that in a single trip down through the
> > stack. Hopefully this should keep CPU usage advantages of TSO for
> > servers that spend most of their time sending replies that are 10MSS
> > or less, while not making the on-the-wire behavior much burstier than
> > it would be with the patch as it stands.
> >
>
> Yes, this sounds an interesting idea.
>
> Problem is that if the application does a sendmsg( 1 Mbytes) right after
> accept(), we'll cook 14KB TSO packets and are back to initial problem.
>
> Quite frankly TSO advantage for servers sending replies that are 10MSS
> or less is thin, because we spend most of cpu cycles in socket
> setup/dismantle and ACK processing.
>
> TSO is a win for sockets sending say more than 100KB, or even 1MB
>
>
>
> > I am wondering about the aspect of the patch that sets sk_pacing_rate
> > to 2x the current rate in tcp_rtt_estimator and then just has to
> > divide by 2 again in tcp_xmit_size_goal(). It seems the 2x factor is
> > natural in the packet scheduler context, but at first glance it feels
> > to me like the multiplication by 2 should be an internal detail of the
> > optional scheduler, not part of the sk_pacing_rate interface between
> > the TCP and scheduling layer.
>
> I would like to keep FQ as simple as possible, and let the transport
> decide for appropriate strategy.
>
> TCP should be the appropriate place to decide on precise delays between
> packets. Packet scheduler will only execute the orders coming from TCP.
>
> In this patch, I chose a 200% factor that is conservative enough to make
> sure there will be no change in the ramp up. It can later be changed to
> get finer control.
>
> >
> > One thing I noticed: something about how the current patch shakes out
> > causes a basic 10-MSS transfer to take an extra RTT, due to the last
> > 2-segment packet having to wait for an ACK:
> >
> > # cat iw10-base-case.pkt
> > 0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
> > 0.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
> > 0.000 bind(3, ..., ...) = 0
> > 0.000 listen(3, 1) = 0
> >
> > 0.100 < S 0:0(0) win 32792 <mss 1460,sackOK,nop,nop,nop,wscale 7>
> > 0.100 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 6>
> > 0.200 < . 1:1(0) ack 1 win 257
> > 0.200 accept(3, ..., ...) = 4
> >
> > 0.200 write(4, ..., 14600) = 14600
> > 0.300 < . 1:1(0) ack 11681 win 257
> >
> > ->
> >
> > # ./packetdrill iw10-base-case.pkt
> > 0.701287 cli > srv: S 0:0(0) win 32792 <mss 1460,sackOK,nop,nop,nop,wscale 7>
> > 0.701367 srv > cli: S 2822928622:2822928622(0) ack 1 win 29200 <mss
> > 1460,nop,nop,sackOK,nop,wscale 6>
> > 0.801276 cli > srv: . ack 1 win 257
> > 0.801365 srv > cli: . 1:2921(2920) ack 1 win 457
> > 0.801376 srv > cli: . 2921:5841(2920) ack 1 win 457
> > 0.801382 srv > cli: . 5841:8761(2920) ack 1 win 457
> > 0.801386 srv > cli: . 8761:11681(2920) ack 1 win 457
> > 0.901284 cli > srv: . ack 11681 win 257
> > 0.901308 srv > cli: P 11681:14601(2920) ack 1 win 457
> >
> > I'd try to isolate the exact cause, but it's a bit late in the evening
> > for me to track this down at this point, and I'll be offline tomorrow.
>
> Interesting, but I do not see this on normal ethernet device (bnx2x in
> the following traces)
I suspect the issue is triggered by when write size is between 9 to 10
full MSS packets. e.g., Neal's packetdrill test is writing data of 10
full size mss. I was able to reproduce this from both packetdrill and
a toy socket program on a real network (~62ms RTT, 1430 MSS). Here is
the tcpdump with relative timings (-ttt).
13000 bytes init write size:
20. 948886 IP 10.246.17.76.60429 > srv: S 3733683575:3733683575(0) win
29200 <mss 1460,nop,nop,sackOK,nop,wscale 6>
062381 IP srv > 10.246.17.76.60429: S 871819030:871819030(0) ack
3733683576 win 62920 <mss 1430,nop,nop,sackOK,nop,wscale 6>
000022 IP 10.246.17.76.60429 > srv: . ack 1 win 457
000022 IP 10.246.17.76.60429 > srv: . 1:2861(2860) ack 1 win 457
000009 IP 10.246.17.76.60429 > srv: . 2861:5721(2860) ack 1 win 457
000010 IP 10.246.17.76.60429 > srv: . 5721:8581(2860) ack 1 win 457
000004 IP 10.246.17.76.60429 > srv: . 8581:11441(2860) ack 1 win 457
062604 IP srv > 10.246.17.76.60429: . ack 11441 win 858
000019 IP 10.246.17.76.60429 > srv: . 11441:12871(1430) ack 1 win 457
000004 IP 10.246.17.76.60429 > srv: P 12871:13001(130) ack 1 win 457
14300 bytes init write size:
lpq76:/export/hda3/tmp/gtests/net/tcp# /tmp/pacing srv 14300
22. 467698 IP cli > srv: S 2400920852:2400920852(0) win 29200 <mss
1460,nop,nop,sackOK,nop,wscale 6>
062536 IP srv > cli: S 2816755090:2816755090(0) ack 2400920853 win
62920 <mss 1430,nop,nop,sackOK,nop,wscale 6>
000017 IP cli > srv: . ack 1 win 457
000016 IP cli > srv: . 1:2861(2860) ack 1 win 457
000008 IP cli > srv: . 2861:5721(2860) ack 1 win 457
000013 IP cli > srv: . 5721:8581(2860) ack 1 win 457
000007 IP cli > srv: . 8581:11441(2860) ack 1 win 457
062745 IP srv > cli: . ack 11441 win 858
000013 IP cli > srv: P 11441:14301(2860) ack 1 win 457
Any idea to get rid of this undesirable extra RTT delay?
Also we probably want to update the rate when both RTT and cwnd are
updated (i.e., after fastretrans_alert()), and the code really
deserves a separate function since it's a major feature. i.e.,
+/* Set the transmission rate of TSO segs in the packet scheduler to
+ * reduce the bursts created by TCP. Note: this is not the conventional
+ * TCP pacing. TCP is still ack-clocked and window based, but we
+ * smooth the burst on large write when packets in flight is significantly
+ * lower than cwnd (or rwin).
+ */
+static void tcp_update_tso_segs_pacing(struct sock* sk)
+{
+ struct tcp_sock *tp = tcp_sk(sk);
+ /* Pacing: -> set sk_pacing_rate to 200 % of current rate */
+ u64 rate = (u64)tp->mss_cache * 8 * 2 * USEC_PER_SEC;
+
+ rate *= max(tp->snd_cwnd, tp->packets_out);
+ do_div(rate, jiffies_to_usecs(tp->srtt));
+ /* Correction for small srtt : minimum srtt being 8 (1 ms),
+ * be conservative and assume rtt = 125 us instead of 1 ms
+ * We probably need usec resolution in the future.
+ */
+ if (tp->srtt <= 8 + 2)
+ rate <<= 3;
+ sk->sk_pacing_rate = min_t(u64, rate, ~0U);
+ pr_debug("cwnd %u packets_out %u srtt %u -> rate = %llu bits\n",
+ tp->snd_cwnd, tp->packets_out,
+ jiffies_to_usecs(tp->srtt) >> 3, rate << 3);
+}
+
/* This routine deals with incoming acks, but not outgoing ones. */
static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
{
@@ -3295,7 +3304,7 @@ static int tcp_ack(struct sock *sk, const struct
sk_buff *skb, int flag)
u32 ack_seq = TCP_SKB_CB(skb)->seq;
u32 ack = TCP_SKB_CB(skb)->ack_seq;
bool is_dupack = false;
- u32 prior_in_flight;
+ u32 prior_in_flight, prior_cwnd = tp->snd_cwnd, prior_rtt = tp->srtt;
u32 prior_fackets;
int prior_packets = tp->packets_out;
const int prior_unsacked = tp->packets_out - tp->sacked_out;
@@ -3400,6 +3409,9 @@ static int tcp_ack(struct sock *sk, const struct
sk_buff *skb, int flag)
if (icsk->icsk_pending == ICSK_TIME_RETRANS)
tcp_schedule_loss_probe(sk);
+
+ if (tp->srtt != prior_rtt || tp->snd_cwnd != prior_cwnd)
+ tcp_update_tso_segs_pacing(sk);
return 1;
no_queue:
>
> Trying different min_tso_segs exhibits expected different behavior (10
> first MSS (14480 bytes of payload) sent in the same ms, no need to wait
> an ACK. (RTT = 50ms in this setup)
>
> echo 1 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:40:35.333703 IP 10.246.17.83.50336 > 10.246.17.84.50267: S 3924987356:3924987356(0) win 29200 <mss 1460,sackOK,timestamp 64807623 0,nop,wscale 6>
> 10:40:35.383835 IP 10.246.17.84.50267 > 10.246.17.83.50336: S 151800535:151800535(0) ack 3924987357 win 28960 <mss 1460,sackOK,timestamp 137049930 64807623,nop,wscale 7>
> 10:40:35.383868 IP 10.246.17.83.50336 > 10.246.17.84.50267: . ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383936 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 1:1449(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383943 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 1449:2897(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383948 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 2897:4345(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383952 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 4345:5793(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383957 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 5793:7241(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383961 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 7241:8689(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383965 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 8689:10137(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383968 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 10137:11585(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383972 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 11585:13033(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.383975 IP 10.246.17.83.50336 > 10.246.17.84.50267: . 13033:14481(1448) ack 1 win 457 <nop,nop,timestamp 64807673 137049930>
> 10:40:35.434061 IP 10.246.17.84.50267 > 10.246.17.83.50336: . ack 1449 win 249 <nop,nop,timestamp 137049981 64807673>
>
> echo 2 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:45:24.280183 IP 10.246.17.83.36666 > 10.246.17.84.40648: S 1657754774:1657754774(0) win 29200 <mss 1460,sackOK,timestamp 65096569 0,nop,wscale 6>
> 10:45:24.330302 IP 10.246.17.84.40648 > 10.246.17.83.36666: S 362153932:362153932(0) ack 1657754775 win 28960 <mss 1460,sackOK,timestamp 137338877 65096569,nop,wscale 7>
> 10:45:24.330384 IP 10.246.17.83.36666 > 10.246.17.84.40648: . ack 1 win 457 <nop,nop,timestamp 65096620 137338877>
> 10:45:24.330477 IP 10.246.17.83.36666 > 10.246.17.84.40648: . 1:2897(2896) ack 1 win 457 <nop,nop,timestamp 65096620 137338877>
> 10:45:24.330497 IP 10.246.17.83.36666 > 10.246.17.84.40648: . 2897:5793(2896) ack 1 win 457 <nop,nop,timestamp 65096620 137338877>
> 10:45:24.330501 IP 10.246.17.83.36666 > 10.246.17.84.40648: . 5793:8689(2896) ack 1 win 457 <nop,nop,timestamp 65096620 137338877>
> 10:45:24.330665 IP 10.246.17.83.36666 > 10.246.17.84.40648: . 8689:11585(2896) ack 1 win 457 <nop,nop,timestamp 65096620 137338877>
> 10:45:24.330674 IP 10.246.17.83.36666 > 10.246.17.84.40648: . 11585:14481(2896) ack 1 win 457 <nop,nop,timestamp 65096620 137338877>
> 10:45:24.380592 IP 10.246.17.84.40648 > 10.246.17.83.36666: . ack 1449 win 249 <nop,nop,timestamp 137338927 65096620>
>
> echo 3 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:48:51.558662 IP 10.246.17.83.44835 > 10.246.17.84.56145: S 2572155347:2572155347(0) win 29200 <mss 1460,sackOK,timestamp 65303848 0,nop,wscale 6>
> 10:48:51.608797 IP 10.246.17.84.56145 > 10.246.17.83.44835: S 2206641454:2206641454(0) ack 2572155348 win 28960 <mss 1460,sackOK,timestamp 137546155 65303848,nop,wscale 7>
> 10:48:51.608824 IP 10.246.17.83.44835 > 10.246.17.84.56145: . ack 1 win 457 <nop,nop,timestamp 65303898 137546155>
> 10:48:51.608901 IP 10.246.17.83.44835 > 10.246.17.84.56145: . 1:4345(4344) ack 1 win 457 <nop,nop,timestamp 65303898 137546155>
> 10:48:51.608911 IP 10.246.17.83.44835 > 10.246.17.84.56145: . 4345:8689(4344) ack 1 win 457 <nop,nop,timestamp 65303898 137546155>
> 10:48:51.608917 IP 10.246.17.83.44835 > 10.246.17.84.56145: . 8689:13033(4344) ack 1 win 457 <nop,nop,timestamp 65303898 137546155>
> 10:48:51.608927 IP 10.246.17.83.44835 > 10.246.17.84.56145: . 13033:14481(1448) ack 1 win 457 <nop,nop,timestamp 65303898 137546155>
> 10:48:51.659018 IP 10.246.17.84.56145 > 10.246.17.83.44835: . ack 1449 win 249 <nop,nop,timestamp 137546206 65303898>
> 10:48:51.659102 IP 10.246.17.83.44835 > 10.246.17.84.56145: . 14481:17377(2896) ack 1 win 457 <nop,nop,timestamp 65303948 137546206>
> 10:48:51.659019 IP 10.246.17.84.56145 > 10.246.17.83.44835: . ack 2897 win 272 <nop,nop,timestamp 137546206 65303898>
> 10:48:51.659113 IP 10.246.17.83.44835 > 10.246.17.84.56145: P 17377:18825(1448) ack 1 win 457 <nop,nop,timestamp 65303948 137546206>
> 10:48:51.659124 IP 10.246.17.84.56145 > 10.246.17.83.44835: . ack 4345 win 295 <nop,nop,timestamp 137546206 65303898>
>
> echo 4 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:49:41.553016 IP 10.246.17.83.51499 > 10.246.17.84.37071: S 770187706:770187706(0) win 29200 <mss 1460,sackOK,timestamp 65353842 0,nop,wscale 6>
> 10:49:41.603149 IP 10.246.17.84.37071 > 10.246.17.83.51499: S 3342827191:3342827191(0) ack 770187707 win 28960 <mss 1460,sackOK,timestamp 137596150 65353842,nop,wscale 7>
> 10:49:41.603223 IP 10.246.17.83.51499 > 10.246.17.84.37071: . ack 1 win 457 <nop,nop,timestamp 65353892 137596150>
> 10:49:41.603307 IP 10.246.17.83.51499 > 10.246.17.84.37071: . 1:5793(5792) ack 1 win 457 <nop,nop,timestamp 65353893 137596150>
> 10:49:41.603317 IP 10.246.17.83.51499 > 10.246.17.84.37071: . 5793:11585(5792) ack 1 win 457 <nop,nop,timestamp 65353893 137596150>
> 10:49:41.603329 IP 10.246.17.83.51499 > 10.246.17.84.37071: . 11585:14481(2896) ack 1 win 457 <nop,nop,timestamp 65353893 137596150>
> 10:49:41.653448 IP 10.246.17.84.37071 > 10.246.17.83.51499: . ack 1449 win 249 <nop,nop,timestamp 137596200 65353893>
> 10:49:41.653531 IP 10.246.17.83.51499 > 10.246.17.84.37071: . 14481:17377(2896) ack 1 win 457 <nop,nop,timestamp 65353943 137596200>
> 10:49:41.653450 IP 10.246.17.84.37071 > 10.246.17.83.51499: . ack 2897 win 272 <nop,nop,timestamp 137596200 65353893>
> 10:49:41.653618 IP 10.246.17.83.51499 > 10.246.17.84.37071: . 17377:20273(2896) ack 1 win 457 <nop,nop,timestamp 65353943 137596200>
>
> echo 5 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:50:33.626270 IP 10.246.17.83.52633 > 10.246.17.84.33693: S 1635294551:1635294551(0) win 29200 <mss 1460,sackOK,timestamp 65405916 0,nop,wscale 6>
> 10:50:33.676407 IP 10.246.17.84.33693 > 10.246.17.83.52633: S 1023650170:1023650170(0) ack 1635294552 win 28960 <mss 1460,sackOK,timestamp 137648223 65405916,nop,wscale 7>
> 10:50:33.676489 IP 10.246.17.83.52633 > 10.246.17.84.33693: . ack 1 win 457 <nop,nop,timestamp 65405966 137648223>
> 10:50:33.676571 IP 10.246.17.83.52633 > 10.246.17.84.33693: . 1:7241(7240) ack 1 win 457 <nop,nop,timestamp 65405966 137648223>
> 10:50:33.676578 IP 10.246.17.83.52633 > 10.246.17.84.33693: . 7241:14481(7240) ack 1 win 457 <nop,nop,timestamp 65405966 137648223>
> 10:50:33.726706 IP 10.246.17.84.33693 > 10.246.17.83.52633: . ack 1449 win 249 <nop,nop,timestamp 137648273 65405966>
> 10:50:33.726707 IP 10.246.17.84.33693 > 10.246.17.83.52633: . ack 2897 win 272 <nop,nop,timestamp 137648273 65405966>
> 10:50:33.726792 IP 10.246.17.83.52633 > 10.246.17.84.33693: . 14481:20273(5792) ack 1 win 457 <nop,nop,timestamp 65406016 137648273>
> 10:50:33.726781 IP 10.246.17.84.33693 > 10.246.17.83.52633: . ack 4345 win 295 <nop,nop,timestamp 137648273 65405966>
> 10:50:33.726986 IP 10.246.17.84.33693 > 10.246.17.83.52633: . ack 5793 win 317 <nop,nop,timestamp 137648274 65405966>
> 10:50:33.727101 IP 10.246.17.84.33693 > 10.246.17.83.52633: . ack 7241 win 340 <nop,nop,timestamp 137648274 65405966>
> 10:50:33.727117 IP 10.246.17.83.52633 > 10.246.17.84.33693: P 20273:27513(7240) ack 1 win 457 <nop,nop,timestamp 65406016 137648274>
> 10:50:33.727258 IP 10.246.17.84.33693 > 10.246.17.83.52633: . ack 8689 win 340 <nop,nop,timestamp 137648274 65405966>
> 10:50:33.727408 IP 10.246.17.84.33693 > 10.246.17.83.52633: . ack 10137 win 340 <nop,nop,timestamp 137648274 65405966>
>
> echo 6 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:51:23.295063 IP 10.246.17.83.49096 > 10.246.17.84.43872: S 1841824181:1841824181(0) win 29200 <mss 1460,sackOK,timestamp 65455584 0,nop,wscale 6>
> 10:51:23.345207 IP 10.246.17.84.43872 > 10.246.17.83.49096: S 2837501410:2837501410(0) ack 1841824182 win 28960 <mss 1460,sackOK,timestamp 137697892 65455584,nop,wscale 7>
> 10:51:23.345237 IP 10.246.17.83.49096 > 10.246.17.84.43872: . ack 1 win 457 <nop,nop,timestamp 65455635 137697892>
> 10:51:23.345311 IP 10.246.17.83.49096 > 10.246.17.84.43872: . 1:8689(8688) ack 1 win 457 <nop,nop,timestamp 65455635 137697892>
> 10:51:23.345330 IP 10.246.17.83.49096 > 10.246.17.84.43872: . 8689:14481(5792) ack 1 win 457 <nop,nop,timestamp 65455635 137697892>
> 10:51:23.395453 IP 10.246.17.84.43872 > 10.246.17.83.49096: . ack 1449 win 249 <nop,nop,timestamp 137697942 65455635>
> 10:51:23.395454 IP 10.246.17.84.43872 > 10.246.17.83.49096: . ack 2897 win 272 <nop,nop,timestamp 137697942 65455635>
> 10:51:23.395544 IP 10.246.17.83.49096 > 10.246.17.84.43872: . 14481:20273(5792) ack 1 win 457 <nop,nop,timestamp 65455685 137697942>
> 10:51:23.395533 IP 10.246.17.84.43872 > 10.246.17.83.49096: . ack 4345 win 295 <nop,nop,timestamp 137697942 65455635>
> 10:51:23.395631 IP 10.246.17.83.49096 > 10.246.17.84.43872: . 20273:23169(2896) ack 1 win 457 <nop,nop,timestamp 65455685 137697942>
> 10:51:23.395746 IP 10.246.17.84.43872 > 10.246.17.83.49096: . ack 5793 win 317 <nop,nop,timestamp 137697942 65455635>
> 10:51:23.395854 IP 10.246.17.84.43872 > 10.246.17.83.49096: . ack 7241 win 340 <nop,nop,timestamp 137697943 65455635>
> 10:51:23.396049 IP 10.246.17.84.43872 > 10.246.17.83.49096: . ack 8689 win 340 <nop,nop,timestamp 137697943 65455635>
> 10:51:23.396199 IP 10.246.17.83.49096 > 10.246.17.84.43872: P 23169:31857(8688) ack 1 win 457 <nop,nop,timestamp 65455685 137697943>
>
> echo 7 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:51:58.219334 IP 10.246.17.83.58882 > 10.246.17.84.41983: S 3763353310:3763353310(0) win 29200 <mss 1460,sackOK,timestamp 65490509 0,nop,wscale 6>
> 10:51:58.269455 IP 10.246.17.84.41983 > 10.246.17.83.58882: S 1445588492:1445588492(0) ack 3763353311 win 28960 <mss 1460,sackOK,timestamp 137732816 65490509,nop,wscale 7>
> 10:51:58.269536 IP 10.246.17.83.58882 > 10.246.17.84.41983: . ack 1 win 457 <nop,nop,timestamp 65490559 137732816>
> 10:51:58.269634 IP 10.246.17.83.58882 > 10.246.17.84.41983: . 1:10137(10136) ack 1 win 457 <nop,nop,timestamp 65490559 137732816>
> 10:51:58.269646 IP 10.246.17.83.58882 > 10.246.17.84.41983: . 10137:14481(4344) ack 1 win 457 <nop,nop,timestamp 65490559 137732816>
> 10:51:58.319765 IP 10.246.17.84.41983 > 10.246.17.83.58882: . ack 1449 win 249 <nop,nop,timestamp 137732866 65490559>
> 10:51:58.319846 IP 10.246.17.83.58882 > 10.246.17.84.41983: . 14481:17377(2896) ack 1 win 457 <nop,nop,timestamp 65490609 137732866>
> 10:51:58.319767 IP 10.246.17.84.41983 > 10.246.17.83.58882: . ack 2897 win 272 <nop,nop,timestamp 137732866 65490559>
> 10:51:58.319843 IP 10.246.17.84.41983 > 10.246.17.83.58882: . ack 4345 win 295 <nop,nop,timestamp 137732867 65490559>
> 10:51:58.319911 IP 10.246.17.83.58882 > 10.246.17.84.41983: . 17377:23169(5792) ack 1 win 457 <nop,nop,timestamp 65490609 137732867>
> 10:51:58.320068 IP 10.246.17.84.41983 > 10.246.17.83.58882: . ack 5793 win 317 <nop,nop,timestamp 137732867 65490559>
> 10:51:58.320180 IP 10.246.17.84.41983 > 10.246.17.83.58882: . ack 7241 win 340 <nop,nop,timestamp 137732867 65490559>
> 10:51:58.320287 IP 10.246.17.84.41983 > 10.246.17.83.58882: . ack 8689 win 340 <nop,nop,timestamp 137732867 65490559>
> 10:51:58.320295 IP 10.246.17.83.58882 > 10.246.17.84.41983: . 23169:31857(8688) ack 1 win 457 <nop,nop,timestamp 65490610 137732867>
> 10:51:58.320496 IP 10.246.17.84.41983 > 10.246.17.83.58882: . ack 10137 win 340 <nop,nop,timestamp 137732867 65490559>
> 10:51:58.320513 IP 10.246.17.83.58882 > 10.246.17.84.41983: . 31857:33305(1448) ack 1 win 457 <nop,nop,timestamp 65490610 137732867>
>
> echo 8 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:52:50.398941 IP 10.246.17.83.32908 > 10.246.17.84.65099: S 678482142:678482142(0) win 29200 <mss 1460,sackOK,timestamp 65542688 0,nop,wscale 6>
> 10:52:50.449061 IP 10.246.17.84.65099 > 10.246.17.83.32908: S 3229813359:3229813359(0) ack 678482143 win 28960 <mss 1460,sackOK,timestamp 137784996 65542688,nop,wscale 7>
> 10:52:50.449146 IP 10.246.17.83.32908 > 10.246.17.84.65099: . ack 1 win 457 <nop,nop,timestamp 65542738 137784996>
> 10:52:50.449258 IP 10.246.17.83.32908 > 10.246.17.84.65099: . 1:11585(11584) ack 1 win 457 <nop,nop,timestamp 65542739 137784996>
> 10:52:50.449384 IP 10.246.17.83.32908 > 10.246.17.84.65099: . 11585:14481(2896) ack 1 win 457 <nop,nop,timestamp 65542739 137784996>
> 10:52:50.499379 IP 10.246.17.84.65099 > 10.246.17.83.32908: . ack 1449 win 249 <nop,nop,timestamp 137785046 65542739>
> 10:52:50.499462 IP 10.246.17.83.32908 > 10.246.17.84.65099: . 14481:17377(2896) ack 1 win 457 <nop,nop,timestamp 65542789 137785046>
> 10:52:50.499381 IP 10.246.17.84.65099 > 10.246.17.83.32908: . ack 2897 win 272 <nop,nop,timestamp 137785046 65542739>
> 10:52:50.499552 IP 10.246.17.83.32908 > 10.246.17.84.65099: . 17377:20273(2896) ack 1 win 457 <nop,nop,timestamp 65542789 137785046>
> 10:52:50.499552 IP 10.246.17.84.65099 > 10.246.17.83.32908: . ack 4345 win 295 <nop,nop,timestamp 137785046 65542739>
> 10:52:50.499661 IP 10.246.17.84.65099 > 10.246.17.83.32908: . ack 5793 win 317 <nop,nop,timestamp 137785046 65542739>
> 10:52:50.499806 IP 10.246.17.84.65099 > 10.246.17.83.32908: . ack 7241 win 340 <nop,nop,timestamp 137785046 65542739>
> 10:52:50.499845 IP 10.246.17.83.32908 > 10.246.17.84.65099: . 20273:28961(8688) ack 1 win 457 <nop,nop,timestamp 65542789 137785046>
> 10:52:50.500006 IP 10.246.17.84.65099 > 10.246.17.83.32908: . ack 8689 win 340 <nop,nop,timestamp 137785047 65542739>
>
> echo 9 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:53:31.504788 IP 10.246.17.83.59687 > 10.246.17.84.38716: S 1238515537:1238515537(0) win 29200 <mss 1460,sackOK,timestamp 65583794 0,nop,wscale 6>
> 10:53:31.554898 IP 10.246.17.84.38716 > 10.246.17.83.59687: S 667062900:667062900(0) ack 1238515538 win 28960 <mss 1460,sackOK,timestamp 137826102 65583794,nop,wscale 7>
> 10:53:31.554973 IP 10.246.17.83.59687 > 10.246.17.84.38716: . ack 1 win 457 <nop,nop,timestamp 65583844 137826102>
> 10:53:31.555050 IP 10.246.17.83.59687 > 10.246.17.84.38716: . 1:13033(13032) ack 1 win 457 <nop,nop,timestamp 65583844 137826102>
> 10:53:31.555072 IP 10.246.17.83.59687 > 10.246.17.84.38716: . 13033:14481(1448) ack 1 win 457 <nop,nop,timestamp 65583844 137826102>
> 10:53:31.605154 IP 10.246.17.84.38716 > 10.246.17.83.59687: . ack 1449 win 249 <nop,nop,timestamp 137826152 65583844>
> 10:53:31.605235 IP 10.246.17.83.59687 > 10.246.17.84.38716: . 14481:17377(2896) ack 1 win 457 <nop,nop,timestamp 65583895 137826152>
> 10:53:31.605156 IP 10.246.17.84.38716 > 10.246.17.83.59687: . ack 2897 win 272 <nop,nop,timestamp 137826152 65583844>
> 10:53:31.605293 IP 10.246.17.84.38716 > 10.246.17.83.59687: . ack 4345 win 295 <nop,nop,timestamp 137826152 65583844>
> 10:53:31.605325 IP 10.246.17.83.59687 > 10.246.17.84.38716: . 17377:23169(5792) ack 1 win 457 <nop,nop,timestamp 65583895 137826152>
> 10:53:31.605461 IP 10.246.17.84.38716 > 10.246.17.83.59687: . ack 5793 win 317 <nop,nop,timestamp 137826152 65583844>
> 10:53:31.605599 IP 10.246.17.84.38716 > 10.246.17.83.59687: . ack 7241 win 340 <nop,nop,timestamp 137826152 65583844>
> 10:53:31.605750 IP 10.246.17.84.38716 > 10.246.17.83.59687: . ack 8689 win 340 <nop,nop,timestamp 137826152 65583844>
> 10:53:31.605834 IP 10.246.17.83.59687 > 10.246.17.84.38716: . 23169:31857(8688) ack 1 win 457 <nop,nop,timestamp 65583895 137826152>
> 10:53:31.605899 IP 10.246.17.84.38716 > 10.246.17.83.59687: . ack 10137 win 340 <nop,nop,timestamp 137826153 65583844>
> 10:53:31.606055 IP 10.246.17.84.38716 > 10.246.17.83.59687: . ack 11585 win 340 <nop,nop,timestamp 137826153 65583844>
> 10:53:31.606155 IP 10.246.17.83.59687 > 10.246.17.84.38716: . 31857:36201(4344) ack 1 win 457 <nop,nop,timestamp 65583895 137826153>
> 10:53:31.606157 IP 10.246.17.84.38716 > 10.246.17.83.59687: . ack 13033 win 340 <nop,nop,timestamp 137826153 65583844>
>
> echo 10 >/proc/sys/net/ipv4/tcp_min_tso_segs
>
> 10:54:15.974831 IP 10.246.17.83.53733 > 10.246.17.84.34163: S 690526362:690526362(0) win 29200 <mss 1460,sackOK,timestamp 65628264 0,nop,wscale 6>
> 10:54:16.024978 IP 10.246.17.84.34163 > 10.246.17.83.53733: S 1914393851:1914393851(0) ack 690526363 win 28960 <mss 1460,sackOK,timestamp 137870572 65628264,nop,wscale 7>
> 10:54:16.025047 IP 10.246.17.83.53733 > 10.246.17.84.34163: . ack 1 win 457 <nop,nop,timestamp 65628314 137870572>
> 10:54:16.025132 IP 10.246.17.83.53733 > 10.246.17.84.34163: . 1:14481(14480) ack 1 win 457 <nop,nop,timestamp 65628314 137870572>
> 10:54:16.075247 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 1449 win 249 <nop,nop,timestamp 137870622 65628314>
> 10:54:16.075249 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 2897 win 272 <nop,nop,timestamp 137870622 65628314>
> 10:54:16.075334 IP 10.246.17.83.53733 > 10.246.17.84.34163: . 14481:20273(5792) ack 1 win 457 <nop,nop,timestamp 65628365 137870622>
> 10:54:16.075452 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 4345 win 295 <nop,nop,timestamp 137870622 65628314>
> 10:54:16.075570 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 5793 win 317 <nop,nop,timestamp 137870622 65628314>
> 10:54:16.075674 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 7241 win 340 <nop,nop,timestamp 137870622 65628314>
> 10:54:16.075698 IP 10.246.17.83.53733 > 10.246.17.84.34163: . 20273:28961(8688) ack 1 win 457 <nop,nop,timestamp 65628365 137870622>
> 10:54:16.075833 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 8689 win 340 <nop,nop,timestamp 137870622 65628314>
> 10:54:16.075990 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 10137 win 340 <nop,nop,timestamp 137870623 65628314>
> 10:54:16.076116 IP 10.246.17.83.53733 > 10.246.17.84.34163: . 28961:34753(5792) ack 1 win 457 <nop,nop,timestamp 65628365 137870623>
> 10:54:16.076096 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 11585 win 340 <nop,nop,timestamp 137870623 65628314>
> 10:54:16.076291 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 13033 win 340 <nop,nop,timestamp 137870623 65628314>
> 10:54:16.076435 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 14481 win 340 <nop,nop,timestamp 137870623 65628314>
> 10:54:16.125492 IP 10.246.17.84.34163 > 10.246.17.83.53733: . ack 15929 win 340 <nop,nop,timestamp 137870672 65628365>
> 10:54:16.125569 IP 10.246.17.83.53733 > 10.246.17.84.34163: . 34753:46337(11584) ack 1 win 457 <nop,nop,timestamp 65628415 137870672>
>
>
>
^ permalink raw reply
* Re: [PATCH RFC net-next] net: epoll support for busy poll
From: Amir Vadai @ 2013-08-25 21:30 UTC (permalink / raw)
To: Eliezer Tamir
Cc: Willem de Bruijn, e1000-devel, netdev, Eilon Greenstein,
linux-kernel, Eric Dumazet, Eric Wong, Eliezer Tamir,
David Miller
In-Reply-To: <52170E78.1010704@linux.intel.com>
[-- Attachment #1.1: Type: text/plain, Size: 1873 bytes --]
I'm on vacation, will test and have some inputs later this week when I be
back.
Amir
On Aug 23, 2013 10:28 AM, "Eliezer Tamir" <eliezer.tamir@linux.intel.com>
wrote:
> On 22/08/2013 23:11, Eric Wong wrote:
> > Eliezer Tamir <eliezer.tamir@linux.intel.com> wrote:
> >> Performance:
> >> using sockperf, Intel X520 NICs,
> >> Supermicro 6026TT-BTF systems with E5-2690 Xeon CPUs
> >> 100 UDP sockets avg. latency 5.756 (std-dev 0.510)
> >> 1k UDP sockets avg. latency 5.780 (std-dev 0.536)
> >> 10k UDP sockets avg. latency 6.269 (std-dev 0.611)
> >
> > How does this compare to with normal poll on this system?
> >
> > In other words, what advantage is there to using epoll instead of poll
> > when busy looping?
> >
> > epoll and busy_poll seem to be opposites. epoll inherently has higher
> > latency than normal poll, but provides stable performance with many more
> > FDs.
>
> I'm not sure I understand your claim that epoll has a higher latency
> than poll.
>
> Some quick (and very unscientific) testing seem to indicate that
> while poll is slightly faster than epoll when polling one socket,
> when polling on three sockets epoll is already slightly faster.
>
> (what's the point of using poll if you only need to monitor one
> socket?)
>
> With a larger socket set epoll is a clear winner.
>
> Both select and poll on 1k UDP sockets take over 120us on a similar
> system.
> Poll on 10 sockets takes about 6.8us, on 100 socket about 16.5us.
>
> Note that I'm using a slightly old NIC that has a high HW latency.
> For comparison, a busy poll on a socket read (using netperf) is about
> 5.7us.
>
> I expect Amir is seeing better numbers, but he's not telling. ;)
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
[-- Attachment #2: Type: text/plain, Size: 379 bytes --]
------------------------------------------------------------------------------
Introducing Performance Central, a new site from SourceForge and
AppDynamics. Performance Central is your source for news, insights,
analysis and resources for efficient Application Performance Management.
Visit us today!
http://pubads.g.doubleclick.net/gampad/clk?id=48897511&iu=/4140/ostg.clktrk
[-- Attachment #3: Type: text/plain, Size: 257 bytes --]
_______________________________________________
E1000-devel mailing list
E1000-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/e1000-devel
To learn more about Intel® Ethernet, visit http://communities.intel.com/community/wired
^ permalink raw reply
* Re: Understanding/reimplementing forwarding acceleration used by Broadcom (ctf)
From: Rafał Miłecki @ 2013-08-25 21:16 UTC (permalink / raw)
To: OpenWrt Development List; +Cc: Network Development
In-Reply-To: <CAKfDRXjYLV1O2jKogpqxGk3tiLtYCQ=mxNZo3=s57Sp0MR0dqQ@mail.gmail.com>
2013/8/24 Kristian Evensen <kristian.evensen@gmail.com>:
> Hi Rafal,
Thanks Kristian for your reply, unfortunately I can't make it work the
way I want :(
> On Sat, Aug 24, 2013 at 5:19 PM, Rafał Miłecki <zajec5@gmail.com> wrote:
>>
>> I wonder what do you think about this solution. Is this something we
>> could try to implement ourself? Is it worth it? Is there some existing
>> project doing similar thing?
>
> This is a very interesting discovery. Have you tried to use etables
> and checked how much data you can push through the router? For
> example, have one machine connected to the LAN and one to the WAN port
> (probably using static IPs for the "WAN" is the easiest). Use MAC NAT
> (http://ebtables.sourceforge.net/examples/basic.html#ex_nat) on the
> OpenWRT router to set the destination to the machine connected to the
> WAN, push UDP traffic from a client connected to the LAN to some
> remote IP and see how much data flows through the router. Use for
> example bwm-ng on the machine connected to the WAN port to see current
> throughput (also to avoid putting any additional pressure on the
> router CPU). Be aware that unless you configure the machine connected
> to the WAN port as a router, the forwarded packets will be discarded.
>
> If this works and gives good performance, based on my understanding,
> you could implement this ctf module as an etables extension.
I've tried to setup network the way you suggested.
I configured OpenWrt router to use static 192.168.5.2 on the WAN
interface and then I set 192.168.5.1 on my monitor (bwm-ng) machine
connected to that WAN port.
OpenWrt uses 192.168.1.1 by default on LAN ports and my second (TX)
machine received some random 192.168.1.131.
I use iperf on my 192.168.1.131 TX machine, so I decided to tell iperf
to use 192.168.1.1 and redirect that traffinc (on the OpenWrt router)
to the WAN port. To do that I typed:
ebtables -t nat -A PREROUTING \
-d $(OPENWRT_MAC) \
-i eth0.1 \
-j dnat --to-destination $(MONITOR_MACHINE_MAC)
eth0.1 interface is the one used for LAN ports and bridged with the br-lan:
# brctl show
bridge name bridge id STP enabled interfaces
br-lan 7fff.204e7fab3aa8 no eth0.1
Then I started:
iperf -c 192.168.1.1 --udp
on my TX machine, but no RX traffic has appeared on my monitor
(192.168.5.1) machine :(
What's worse, after executing that "ebtable" command even direct:
iperf -c 192.168.5.1 --udp
doesn't generate any RX on my monitor (192.168.5.1) machine. Flushing
-t nat makes that direct command work again.
I guess I did something wrong in my ebtables rule. Do you have any
idea what could it be? It's the first time I've heard about ebtables
to be honest.
--
Rafał
_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/cgi-bin/mailman/listinfo/openwrt-devel
^ permalink raw reply
* Re: [systemd-devel] [PATCH] netns: unix: only allow to find out unix socket in same net namespace
From: James Bottomley @ 2013-08-25 18:16 UTC (permalink / raw)
To: Kay Sievers
Cc: systemd-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
libvir-list-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux Containers,
lxc-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org, Eric W. Biederman
In-Reply-To: <CAPXgP115pEE8jxyCqauoMRWui3Qb0fBzPr9L2_SA411=gfnX3w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Sun, 2013-08-25 at 19:37 +0200, Kay Sievers wrote:
> On Sun, Aug 25, 2013 at 7:16 PM, James Bottomley
> <jbottomley-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org> wrote:
> > On Wed, 2013-08-21 at 11:51 +0200, Kay Sievers wrote:
> >> On Wed, Aug 21, 2013 at 9:22 AM, Gao feng <gaofeng-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org> wrote:
> >> > On 08/21/2013 03:06 PM, Eric W. Biederman wrote:
> >>
> >> >> I suspect libvirt should simply not share /run or any other normally
> >> >> writable directory with the host. Sharing /run /var/run or even /tmp
> >> >> seems extremely dubious if you want some kind of containment, and
> >> >> without strange things spilling through.
> >>
> >> Right, /run or /var cannot be shared. It's not only about sockets,
> >> many other things will also go really wrong that way.
> >
> > This is very narrow thinking about what a container might be and will
> > cause trouble as people start to create novel uses for containers in the
> > cloud if you try to impose this on our current infrastructure.
> >
> > One of the cgroup only container uses we see at Parallels (so no
> > separate filesystem and no net namespaces) is pure apache load balancer
> > type shared hosting. In this scenario, base apache is effectively
> > brought up in the host environment, but then spawned instances are
> > resource limited using cgroups according to what the customer has paid.
> > Obviously all apache instances are sharing /var and /run from the host
> > (mostly for logging and pid storage and static pages). The reason some
> > hosters do this is that it allows much higher density simple web serving
> > (either static pages from quota limited chroots or dynamic pages limited
> > by database space constraints) because each "instance" shares so much
> > from the host. The service is obviously much more basic than giving
> > each customer a container running apache, but it's much easier for the
> > hoster to administer and it serves the customer just as well for a large
> > cross section of use cases and for those it doesn't serve, the hoster
> > usually has separate container hosting (for a higher price, of course).
>
> The "container" as we talk about has it's own init, and no, it cannot
> share /var or /run.
This is what we would call an IaaS container: bringing up init and
effectively a new OS inside a container is the closest containers come
to being like hypervisors. It's the most common use case of Parallels
containers in the field, so I'm certainly not telling you it's a bad
idea.
> The stuff you talk about has nothing to do with that, it's not
> different from all services or a multi-instantiated service on the
> host sharing the same /run and /var.
I gave you one example: a really simplistic one. A more sophisticated
example is a PaaS or SaaS container where you bring the OS up in the
host but spawn a particular application into its own container (this is
essentially similar to what Docker does). Often in this case, you do
add separate mount and network namespaces to make the application
isolated and migrateable with its own IP address. The reason you share
init and most of the OS from the host is for elasticity and density,
which are fast becoming a holy grail type quest of cloud orchestration
systems: if you don't have to bring up the OS from init and you can just
start the application from a C/R image (orders of magnitude smaller than
a full system image) and slap on the necessary namespaces as you clone
it, you have something that comes online in miliseconds which is a feat
no hypervisor based virtualisation can match.
I'm not saying don't pursue the IaaS case, it's definitely useful ...
I'm just saying it would be a serious mistake to think that's the only
use case for containers and we certainly shouldn't adjust Linux to serve
only that use case.
James
^ permalink raw reply
* [PATCH 2/2] tcp: syncookies: reduce mss table to four values
From: Florian Westphal @ 2013-08-25 17:54 UTC (permalink / raw)
To: netdev; +Cc: jbohac, Florian Westphal
In-Reply-To: <1377453242-4773-1-git-send-email-fw@strlen.de>
Halve mss table size to make blind cookie guessing more difficult.
This is sad since the tables were already small, but there
is little alternative except perhaps adding more precise mss information
in the tcp timestamp. Timestamps are unfortunately not ubiquitous.
Guessing all possible cookie values still has 8-in 2**32 chance.
Reported-by: Jakob Lell <jakob@jakoblell.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
Another argument AGAINST this patch is that if 16-in 2**32 is
too easy then 8-in-2**32 will be doable, too.
net/ipv4/syncookies.c | 6 +-----
net/ipv6/syncookies.c | 4 ----
2 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index e2f84eb..fd52401 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -143,14 +143,10 @@ static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
* Table must be sorted.
*/
static __u16 const msstab[] = {
- 64,
- 512,
536,
- 1024,
+ 1200,
1440,
1460,
- 4312,
- 8960,
};
/*
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 6a6d585..cc4513b 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -27,13 +27,9 @@
/* Table must be sorted. */
static __u16 const msstab[] = {
- 64,
- 512,
- 536,
1280 - 60,
1480 - 60,
1500 - 60,
- 4460 - 60,
9000 - 60,
};
--
1.8.1.5
^ permalink raw reply related
* [PATCH 1/2] tcp: syncookies: reduce cookie lifetime to 128 seconds
From: Florian Westphal @ 2013-08-25 17:54 UTC (permalink / raw)
To: netdev; +Cc: jbohac, Florian Westphal
We currently accept cookies that were created less than 4 minutes ago
(ie, cookies with counter delta 0-3). Combined with the 8 mss table
values, this yields 32 possible values (out of 2**32) that will be valid.
Reducing the lifetime to < 2 minutes halves the guessing chance while
still providing a large enough period (possible cookies are
only validated if last synqueue overflow was less than 3 seconds ago).
While at it, get rid of jiffies value -- they overflow too quickly on
32 bit platforms.
getnstimeofday is used to create a counter that increments every 64s.
Reported-by: Jakob Lell <jakob@jakoblell.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
include/net/tcp.h | 12 ++++++++++++
net/ipv4/syncookies.c | 32 ++++++++++----------------------
net/ipv6/syncookies.c | 25 ++++++++-----------------
3 files changed, 30 insertions(+), 39 deletions(-)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 09cb5c1..89368db 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -478,7 +478,19 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb);
extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS];
extern struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
struct ip_options *opt);
+
+#define MAX_SYNCOOKIE_AGE 2 /* 128 seconds */
+
#ifdef CONFIG_SYN_COOKIES
+#include <linux/ktime.h>
+
+static inline u32 tcp_cookie_time(void)
+{
+ struct timespec now;
+ getnstimeofday(&now);
+ return now.tv_sec >> 6; /* 64 seconds granularity */
+}
+
extern __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb,
__u16 *mss);
#else
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
index b05c96e..e2f84eb 100644
--- a/net/ipv4/syncookies.c
+++ b/net/ipv4/syncookies.c
@@ -87,10 +87,8 @@ __u32 cookie_init_timestamp(struct request_sock *req)
return ts;
}
-
static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
- __be16 dport, __u32 sseq, __u32 count,
- __u32 data)
+ __be16 dport, __u32 sseq, __u32 data)
{
/*
* Compute the secure sequence number.
@@ -102,7 +100,7 @@ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
* As an extra hack, we add a small "data" value that encodes the
* MSS into the second hash value.
*/
-
+ u32 count = tcp_cookie_time();
return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
sseq + (count << COOKIEBITS) +
((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
@@ -114,22 +112,21 @@ static __u32 secure_tcp_syn_cookie(__be32 saddr, __be32 daddr, __be16 sport,
* If the syncookie is bad, the data returned will be out of
* range. This must be checked by the caller.
*
- * The count value used to generate the cookie must be within
- * "maxdiff" if the current (passed-in) "count". The return value
- * is (__u32)-1 if this test fails.
+ * The count value used to generate the cookie must be less than
+ * MAX_SYNCOOKIE_AGE minutes in the past.
+ * The return value (__u32)-1 if this test fails.
*/
static __u32 check_tcp_syn_cookie(__u32 cookie, __be32 saddr, __be32 daddr,
- __be16 sport, __be16 dport, __u32 sseq,
- __u32 count, __u32 maxdiff)
+ __be16 sport, __be16 dport, __u32 sseq)
{
- __u32 diff;
+ u32 diff, count = tcp_cookie_time();
/* Strip away the layers from the cookie */
cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */
diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS);
- if (diff >= maxdiff)
+ if (diff >= MAX_SYNCOOKIE_AGE)
return (__u32)-1;
return (cookie -
@@ -178,17 +175,10 @@ __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp)
return secure_tcp_syn_cookie(iph->saddr, iph->daddr,
th->source, th->dest, ntohl(th->seq),
- jiffies / (HZ * 60), mssind);
+ mssind);
}
/*
- * This (misnamed) value is the age of syncookie which is permitted.
- * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
- * sysctl_tcp_retries1. It's a rather complicated formula (exponential
- * backoff) to compute at runtime so it's currently hardcoded here.
- */
-#define COUNTER_TRIES 4
-/*
* Check if a ack sequence number is a valid syncookie.
* Return the decoded mss if it is, or 0 if not.
*/
@@ -198,9 +188,7 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie)
const struct tcphdr *th = tcp_hdr(skb);
__u32 seq = ntohl(th->seq) - 1;
__u32 mssind = check_tcp_syn_cookie(cookie, iph->saddr, iph->daddr,
- th->source, th->dest, seq,
- jiffies / (HZ * 60),
- COUNTER_TRIES);
+ th->source, th->dest, seq);
return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;
}
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index d5dda20..6a6d585 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -18,6 +18,7 @@
#include <linux/random.h>
#include <linux/cryptohash.h>
#include <linux/kernel.h>
+#include <linux/ktime.h>
#include <net/ipv6.h>
#include <net/tcp.h>
@@ -36,14 +37,6 @@ static __u16 const msstab[] = {
9000 - 60,
};
-/*
- * This (misnamed) value is the age of syncookie which is permitted.
- * Its ideal value should be dependent on TCP_TIMEOUT_INIT and
- * sysctl_tcp_retries1. It's a rather complicated formula (exponential
- * backoff) to compute at runtime so it's currently hardcoded here.
- */
-#define COUNTER_TRIES 4
-
static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,
struct request_sock *req,
struct dst_entry *dst)
@@ -86,8 +79,9 @@ static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *dadd
static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
const struct in6_addr *daddr,
__be16 sport, __be16 dport, __u32 sseq,
- __u32 count, __u32 data)
+ __u32 data)
{
+ u32 count = tcp_cookie_time();
return (cookie_hash(saddr, daddr, sport, dport, 0, 0) +
sseq + (count << COOKIEBITS) +
((cookie_hash(saddr, daddr, sport, dport, count, 1) + data)
@@ -96,15 +90,14 @@ static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr,
static __u32 check_tcp_syn_cookie(__u32 cookie, const struct in6_addr *saddr,
const struct in6_addr *daddr, __be16 sport,
- __be16 dport, __u32 sseq, __u32 count,
- __u32 maxdiff)
+ __be16 dport, __u32 sseq)
{
- __u32 diff;
+ __u32 diff, count = tcp_cookie_time();
cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq;
diff = (count - (cookie >> COOKIEBITS)) & ((__u32) -1 >> COOKIEBITS);
- if (diff >= maxdiff)
+ if (diff >= MAX_SYNCOOKIE_AGE)
return (__u32)-1;
return (cookie -
@@ -130,8 +123,7 @@ __u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb, __u16
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_SYNCOOKIESSENT);
return secure_tcp_syn_cookie(&iph->saddr, &iph->daddr, th->source,
- th->dest, ntohl(th->seq),
- jiffies / (HZ * 60), mssind);
+ th->dest, ntohl(th->seq), mssind);
}
static inline int cookie_check(const struct sk_buff *skb, __u32 cookie)
@@ -140,8 +132,7 @@ static inline int cookie_check(const struct sk_buff *skb, __u32 cookie)
const struct tcphdr *th = tcp_hdr(skb);
__u32 seq = ntohl(th->seq) - 1;
__u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr,
- th->source, th->dest, seq,
- jiffies / (HZ * 60), COUNTER_TRIES);
+ th->source, th->dest, seq);
return mssind < ARRAY_SIZE(msstab) ? msstab[mssind] : 0;
}
--
1.8.1.5
^ permalink raw reply related
* Re: [systemd-devel] [PATCH] netns: unix: only allow to find out unix socket in same net namespace
From: Kay Sievers @ 2013-08-25 17:37 UTC (permalink / raw)
To: James Bottomley
Cc: systemd-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
libvir-list-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux Containers,
lxc-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org, Eric W. Biederman
In-Reply-To: <1377450974.8757.41.camel@dabdike>
On Sun, Aug 25, 2013 at 7:16 PM, James Bottomley
<jbottomley-bzQdu9zFT3WakBO8gow8eQ@public.gmane.org> wrote:
> On Wed, 2013-08-21 at 11:51 +0200, Kay Sievers wrote:
>> On Wed, Aug 21, 2013 at 9:22 AM, Gao feng <gaofeng-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org> wrote:
>> > On 08/21/2013 03:06 PM, Eric W. Biederman wrote:
>>
>> >> I suspect libvirt should simply not share /run or any other normally
>> >> writable directory with the host. Sharing /run /var/run or even /tmp
>> >> seems extremely dubious if you want some kind of containment, and
>> >> without strange things spilling through.
>>
>> Right, /run or /var cannot be shared. It's not only about sockets,
>> many other things will also go really wrong that way.
>
> This is very narrow thinking about what a container might be and will
> cause trouble as people start to create novel uses for containers in the
> cloud if you try to impose this on our current infrastructure.
>
> One of the cgroup only container uses we see at Parallels (so no
> separate filesystem and no net namespaces) is pure apache load balancer
> type shared hosting. In this scenario, base apache is effectively
> brought up in the host environment, but then spawned instances are
> resource limited using cgroups according to what the customer has paid.
> Obviously all apache instances are sharing /var and /run from the host
> (mostly for logging and pid storage and static pages). The reason some
> hosters do this is that it allows much higher density simple web serving
> (either static pages from quota limited chroots or dynamic pages limited
> by database space constraints) because each "instance" shares so much
> from the host. The service is obviously much more basic than giving
> each customer a container running apache, but it's much easier for the
> hoster to administer and it serves the customer just as well for a large
> cross section of use cases and for those it doesn't serve, the hoster
> usually has separate container hosting (for a higher price, of course).
The "container" as we talk about has it's own init, and no, it cannot
share /var or /run.
The stuff you talk about has nothing to do with that, it's not
different from all services or a multi-instantiated service on the
host sharing the same /run and /var.
Kay
^ permalink raw reply
* Re: [systemd-devel] [PATCH] netns: unix: only allow to find out unix socket in same net namespace
From: James Bottomley @ 2013-08-25 17:16 UTC (permalink / raw)
To: Kay Sievers
Cc: systemd-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW@public.gmane.org,
libvir-list-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org,
netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Linux Containers,
lxc-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org,
davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org, Eric W. Biederman
In-Reply-To: <CAPXgP120YUEVnFiD0uPnqeO4x=5oRvHL79-cX5CnmEWc3d5mvQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Wed, 2013-08-21 at 11:51 +0200, Kay Sievers wrote:
> On Wed, Aug 21, 2013 at 9:22 AM, Gao feng <gaofeng-BthXqXjhjHXQFUHtdCDX3A@public.gmane.org> wrote:
> > On 08/21/2013 03:06 PM, Eric W. Biederman wrote:
>
> >> I suspect libvirt should simply not share /run or any other normally
> >> writable directory with the host. Sharing /run /var/run or even /tmp
> >> seems extremely dubious if you want some kind of containment, and
> >> without strange things spilling through.
>
> Right, /run or /var cannot be shared. It's not only about sockets,
> many other things will also go really wrong that way.
This is very narrow thinking about what a container might be and will
cause trouble as people start to create novel uses for containers in the
cloud if you try to impose this on our current infrastructure.
One of the cgroup only container uses we see at Parallels (so no
separate filesystem and no net namespaces) is pure apache load balancer
type shared hosting. In this scenario, base apache is effectively
brought up in the host environment, but then spawned instances are
resource limited using cgroups according to what the customer has paid.
Obviously all apache instances are sharing /var and /run from the host
(mostly for logging and pid storage and static pages). The reason some
hosters do this is that it allows much higher density simple web serving
(either static pages from quota limited chroots or dynamic pages limited
by database space constraints) because each "instance" shares so much
from the host. The service is obviously much more basic than giving
each customer a container running apache, but it's much easier for the
hoster to administer and it serves the customer just as well for a large
cross section of use cases and for those it doesn't serve, the hoster
usually has separate container hosting (for a higher price, of course).
James
^ permalink raw reply
* CAN WE PARTNER?
From: Myrna Cooke @ 2013-08-25 14:07 UTC (permalink / raw)
I have a transaction for you, for details contact me
via: mckoenig26@live.com
Mrs Cecilia Koenig
-------------------------
Statement of Confidentiality
This message (including attachments) may contain confidential or privileged information intended for a specific individual or organization. If you have received this communication in error, please notify the sender immediately. If you are not the intended recipient, you are not authorized to use, disclose, distribute, copy, print or rely on this email, and should promptly delete this email from your entire computer system.
^ permalink raw reply
* Re: [PATCH 6/6] vhost_net: remove the max pending check
From: Michael S. Tsirkin @ 2013-08-25 11:53 UTC (permalink / raw)
To: Jason Wang; +Cc: netdev, linux-kernel, kvm, virtualization
In-Reply-To: <52172395.9000400@redhat.com>
On Fri, Aug 23, 2013 at 04:55:49PM +0800, Jason Wang wrote:
> On 08/20/2013 10:48 AM, Jason Wang wrote:
> > On 08/16/2013 06:02 PM, Michael S. Tsirkin wrote:
> >> > On Fri, Aug 16, 2013 at 01:16:30PM +0800, Jason Wang wrote:
> >>> >> We used to limit the max pending DMAs to prevent guest from pinning too many
> >>> >> pages. But this could be removed since:
> >>> >>
> >>> >> - We have the sk_wmem_alloc check in both tun/macvtap to do the same work
> >>> >> - This max pending check were almost useless since it was one done when there's
> >>> >> no new buffers coming from guest. Guest can easily exceeds the limitation.
> >>> >> - We've already check upend_idx != done_idx and switch to non zerocopy then. So
> >>> >> even if all vq->heads were used, we can still does the packet transmission.
> >> > We can but performance will suffer.
> > The check were in fact only done when no new buffers submitted from
> > guest. So if guest keep sending, the check won't be done.
> >
> > If we really want to do this, we should do it unconditionally. Anyway, I
> > will do test to see the result.
>
> There's a bug in PATCH 5/6, the check:
>
> nvq->upend_idx != nvq->done_idx
>
> makes the zerocopy always been disabled since we initialize both
> upend_idx and done_idx to zero. So I change it to:
>
> (nvq->upend_idx + 1) % UIO_MAXIOV != nvq->done_idx.
But what I would really like to try is limit ubuf_info to VHOST_MAX_PEND.
I think this has a chance to improve performance since
we'll be using less cache.
Of course this means we must fix the code to really never submit
more than VHOST_MAX_PEND requests.
Want to try?
>
> With this change on top, I didn't see performance difference w/ and w/o
> this patch.
Did you try small message sizes btw (like 1K)? Or just netperf
default of 64K?
--
MST
^ permalink raw reply
* Re: [PATCH 2/6] vhost_net: use vhost_add_used_and_signal_n() in vhost_zerocopy_signal_used()
From: Michael S. Tsirkin @ 2013-08-25 11:48 UTC (permalink / raw)
To: Jason Wang; +Cc: netdev, linux-kernel, kvm, virtualization
In-Reply-To: <5217225E.2060006@redhat.com>
On Fri, Aug 23, 2013 at 04:50:38PM +0800, Jason Wang wrote:
> On 08/20/2013 10:33 AM, Jason Wang wrote:
> > On 08/16/2013 05:54 PM, Michael S. Tsirkin wrote:
> >> On Fri, Aug 16, 2013 at 01:16:26PM +0800, Jason Wang wrote:
> >>>> Switch to use vhost_add_used_and_signal_n() to avoid multiple calls to
> >>>> vhost_add_used_and_signal(). With the patch we will call at most 2 times
> >>>> (consider done_idx warp around) compared to N times w/o this patch.
> >>>>
> >>>> Signed-off-by: Jason Wang <jasowang@redhat.com>
> >> So? Does this help performance then?
> >>
> > Looks like it can especially when guest does support event index. When
> > guest enable tx interrupt, this can saves us some unnecessary signal to
> > guest. I will do some test.
>
> Have done some test. I can see 2% - 3% increasing in both aggregate
> transaction rate and per cpu transaction rate in TCP_RR and UDP_RR test.
>
> I'm using ixgbe. W/o this patch, I can see more than 100 calls of
> vhost_add_used_signal() in one vhost_zerocopy_signaled_used(). This is
> because ixgbe (and other modern ethernet driver) tends to free old tx
> skbs in a loop during tx interrupt, and vhost tend to batch the adding
> used and signal in vhost_zerocopy_callback(). Switching to use
> vhost_add_use_and_signal_n() means saving 100 times of used idx updating
> and memory barriers.
Well it's only smp_wmb so a nop on most architectures, so
a 2% gain is surprising.
I'm guessing the cache miss on the write is what's
giving us a speedup here.
I'll review the code, thanks.
--
MST
^ permalink raw reply
* pcie_get_minimum_link returns 0 width
From: Yuval Mintz @ 2013-08-25 11:21 UTC (permalink / raw)
To: jacob.e.keller@intel.com
Cc: bhelgaas@google.com, linux-pci@vger.kernel.org,
netdev@vger.kernel.org
In-Reply-To: <20130825100157.GA16500@lb-tlvb-yuvalmin.il.broadcom.com>
Hi,
I tried adding support for the newly added 'pcie_get_minimum_link' into the
bnx2x driver, but found out the some of my devices started showing width x0.
By adding debug prints, I've found out there were devices up the chain that
Showed 0 when their PCI_EXP_LNKSTA was read by said function.
However, when I tried looking via lspci the output claimed the width was x4.
lspci -vt output:
[0000:00]-+-00.0 Intel Corporation 5000P Chipset Memory Controller Hub
+-02.0-[09-12]--+-00.0-[0a-11]--+-00.0-[0b-0d]--
+-01.0-[0e-10]--+-00.0 Broadcom
Corporation NetXtreme II BCM57710
10-Gigabit PCIe [Everest]
Where:
00:02.0 PCI bridge: Intel Corporation 5000 Series Chipset PCI Express x4 Port
2 (rev 93)
09:00.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express Upstream
Port (rev 01)
0a:01.0 PCI bridge: Intel Corporation 6311ESB/6321ESB PCI Express
Downstream Port E2 (rev 01)
0e:00.0 Ethernet controller: Broadcom Corporation NetXtreme II BCM57710
10-Gigabit PCIe [Everest] (rev 01)
The output for "lspci -vvvv | grep LnkSta for all four is:
LnkSta: Speed 2.5GT/s, Width x4, TrErr- Train- SlotClk+ DLActive- BWMgmt-
ABWMgmt-
But added prints inside the function's loop show:
LnkSta 1041 [000e:00.00]
LnkSta 0000 [000a:01.00]
LnkSta 0000 [0009:00.00]
LnkSta 3041 [0000:02.00]
(PCI_EXP_LNKSTA value, bus->number, PCI_SLOT, PCI_FUNC)
Thanks,
Yuval
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox