Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 202618
b: refs/heads/master
c: 90d683a
h: refs/heads/master
v: v3
  • Loading branch information
Steve Hodgson authored and David S. Miller committed Jun 2, 2010
1 parent 833f8f9 commit ad095d1
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 131 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d730dc527a5abd4717f6320e82cfce54edc882a3
refs/heads/master: 90d683afd1395016775c8d90508614f8d3000b81
44 changes: 7 additions & 37 deletions trunk/drivers/net/sfc/efx.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,6 @@ const char *efx_reset_type_names[] = {

#define EFX_MAX_MTU (9 * 1024)

/* RX slow fill workqueue. If memory allocation fails in the fast path,
* a work item is pushed onto this work queue to retry the allocation later,
* to avoid the NIC being starved of RX buffers. Since this is a per cpu
* workqueue, there is nothing to be gained in making it per NIC
*/
static struct workqueue_struct *refill_workqueue;

/* Reset workqueue. If any NIC has a hardware failure then a reset will be
* queued onto this work queue. This is not a per-nic work queue, because
* efx_reset_work() acquires the rtnl lock, so resets are naturally serialised.
Expand Down Expand Up @@ -516,11 +509,11 @@ static void efx_start_channel(struct efx_channel *channel)
channel->enabled = true;
smp_wmb();

napi_enable(&channel->napi_str);

/* Load up RX descriptors */
/* Fill the queues before enabling NAPI */
efx_for_each_channel_rx_queue(rx_queue, channel)
efx_fast_push_rx_descriptors(rx_queue);

napi_enable(&channel->napi_str);
}

/* This disables event queue processing and packet transmission.
Expand All @@ -529,21 +522,13 @@ static void efx_start_channel(struct efx_channel *channel)
*/
static void efx_stop_channel(struct efx_channel *channel)
{
struct efx_rx_queue *rx_queue;

if (!channel->enabled)
return;

EFX_LOG(channel->efx, "stop chan %d\n", channel->channel);

channel->enabled = false;
napi_disable(&channel->napi_str);

/* Ensure that any worker threads have exited or will be no-ops */
efx_for_each_channel_rx_queue(rx_queue, channel) {
spin_lock_bh(&rx_queue->add_lock);
spin_unlock_bh(&rx_queue->add_lock);
}
}

static void efx_fini_channels(struct efx_nic *efx)
Expand Down Expand Up @@ -595,9 +580,9 @@ static void efx_remove_channel(struct efx_channel *channel)
efx_remove_eventq(channel);
}

void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay)
void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue)
{
queue_delayed_work(refill_workqueue, &rx_queue->work, delay);
mod_timer(&rx_queue->slow_fill, jiffies + msecs_to_jiffies(100));
}

/**************************************************************************
Expand Down Expand Up @@ -1242,15 +1227,8 @@ static void efx_start_all(struct efx_nic *efx)
* since we're holding the rtnl_lock at this point. */
static void efx_flush_all(struct efx_nic *efx)
{
struct efx_rx_queue *rx_queue;

/* Make sure the hardware monitor is stopped */
cancel_delayed_work_sync(&efx->monitor_work);

/* Ensure that all RX slow refills are complete. */
efx_for_each_rx_queue(rx_queue, efx)
cancel_delayed_work_sync(&rx_queue->work);

/* Stop scheduled port reconfigurations */
cancel_work_sync(&efx->mac_work);
}
Expand Down Expand Up @@ -2064,8 +2042,8 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
rx_queue->queue = i;
rx_queue->channel = &efx->channel[0]; /* for safety */
rx_queue->buffer = NULL;
spin_lock_init(&rx_queue->add_lock);
INIT_DELAYED_WORK(&rx_queue->work, efx_rx_work);
setup_timer(&rx_queue->slow_fill, efx_rx_slow_fill,
(unsigned long)rx_queue);
}

efx->type = type;
Expand Down Expand Up @@ -2436,11 +2414,6 @@ static int __init efx_init_module(void)
if (rc)
goto err_notifier;

refill_workqueue = create_workqueue("sfc_refill");
if (!refill_workqueue) {
rc = -ENOMEM;
goto err_refill;
}
reset_workqueue = create_singlethread_workqueue("sfc_reset");
if (!reset_workqueue) {
rc = -ENOMEM;
Expand All @@ -2456,8 +2429,6 @@ static int __init efx_init_module(void)
err_pci:
destroy_workqueue(reset_workqueue);
err_reset:
destroy_workqueue(refill_workqueue);
err_refill:
unregister_netdevice_notifier(&efx_netdev_notifier);
err_notifier:
return rc;
Expand All @@ -2469,7 +2440,6 @@ static void __exit efx_exit_module(void)

pci_unregister_driver(&efx_pci_driver);
destroy_workqueue(reset_workqueue);
destroy_workqueue(refill_workqueue);
unregister_netdevice_notifier(&efx_netdev_notifier);

}
Expand Down
4 changes: 2 additions & 2 deletions trunk/drivers/net/sfc/efx.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ extern void efx_init_rx_queue(struct efx_rx_queue *rx_queue);
extern void efx_fini_rx_queue(struct efx_rx_queue *rx_queue);
extern void efx_rx_strategy(struct efx_channel *channel);
extern void efx_fast_push_rx_descriptors(struct efx_rx_queue *rx_queue);
extern void efx_rx_work(struct work_struct *data);
extern void efx_rx_slow_fill(unsigned long context);
extern void __efx_rx_packet(struct efx_channel *channel,
struct efx_rx_buffer *rx_buf, bool checksummed);
extern void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index,
unsigned int len, bool checksummed, bool discard);
extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay);
extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue);
#define EFX_RXQ_SIZE 1024
#define EFX_RXQ_MASK (EFX_RXQ_SIZE - 1)

Expand Down
10 changes: 3 additions & 7 deletions trunk/drivers/net/sfc/net_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/if_vlan.h>
#include <linux/timer.h>
#include <linux/mdio.h>
#include <linux/list.h>
#include <linux/pci.h>
Expand Down Expand Up @@ -242,10 +243,6 @@ struct efx_rx_buffer {
* @added_count: Number of buffers added to the receive queue.
* @notified_count: Number of buffers given to NIC (<= @added_count).
* @removed_count: Number of buffers removed from the receive queue.
* @add_lock: Receive queue descriptor add spin lock.
* This lock must be held in order to add buffers to the RX
* descriptor ring (rxd and buffer) and to update added_count (but
* not removed_count).
* @max_fill: RX descriptor maximum fill level (<= ring size)
* @fast_fill_trigger: RX descriptor fill level that will trigger a fast fill
* (<= @max_fill)
Expand All @@ -259,7 +256,7 @@ struct efx_rx_buffer {
* overflow was observed. It should never be set.
* @alloc_page_count: RX allocation strategy counter.
* @alloc_skb_count: RX allocation strategy counter.
* @work: Descriptor push work thread
* @slow_fill: Timer used to defer efx_nic_generate_fill_event().
* @buf_page: Page for next RX buffer.
* We can use a single page for multiple RX buffers. This tracks
* the remaining space in the allocation.
Expand All @@ -277,15 +274,14 @@ struct efx_rx_queue {
int added_count;
int notified_count;
int removed_count;
spinlock_t add_lock;
unsigned int max_fill;
unsigned int fast_fill_trigger;
unsigned int fast_fill_limit;
unsigned int min_fill;
unsigned int min_overfill;
unsigned int alloc_page_count;
unsigned int alloc_skb_count;
struct delayed_work work;
struct timer_list slow_fill;
unsigned int slow_fill_count;

struct page *buf_page;
Expand Down
49 changes: 39 additions & 10 deletions trunk/drivers/net/sfc/nic.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,14 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
/* Depth of RX flush request fifo */
#define EFX_RX_FLUSH_COUNT 4

/* Magic value for efx_generate_test_event() */
#define EFX_CHANNEL_MAGIC(_channel) \
/* Generated event code for efx_generate_test_event() */
#define EFX_CHANNEL_MAGIC_TEST(_channel) \
(0x00010100 + (_channel)->channel)

/* Generated event code for efx_generate_fill_event() */
#define EFX_CHANNEL_MAGIC_FILL(_channel) \
(0x00010200 + (_channel)->channel)

/**************************************************************************
*
* Solarstorm hardware access
Expand Down Expand Up @@ -854,6 +858,26 @@ efx_handle_rx_event(struct efx_channel *channel, const efx_qword_t *event)
checksummed, discard);
}

static void
efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
{
struct efx_nic *efx = channel->efx;
unsigned code;

code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
if (code == EFX_CHANNEL_MAGIC_TEST(channel))
++channel->magic_count;
else if (code == EFX_CHANNEL_MAGIC_FILL(channel))
/* The queue must be empty, so we won't receive any rx
* events, so efx_process_channel() won't refill the
* queue. Refill it here */
efx_fast_push_rx_descriptors(&efx->rx_queue[channel->channel]);
else
EFX_LOG(efx, "channel %d received generated "
"event "EFX_QWORD_FMT"\n", channel->channel,
EFX_QWORD_VAL(*event));
}

/* Global events are basically PHY events */
static void
efx_handle_global_event(struct efx_channel *channel, efx_qword_t *event)
Expand Down Expand Up @@ -997,13 +1021,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
}
break;
case FSE_AZ_EV_CODE_DRV_GEN_EV:
if (EFX_QWORD_FIELD(event, FSF_AZ_DRV_GEN_EV_MAGIC)
== EFX_CHANNEL_MAGIC(channel))
++channel->magic_count;

EFX_LOG(channel->efx, "channel %d received generated "
"event "EFX_QWORD_FMT"\n", channel->channel,
EFX_QWORD_VAL(event));
efx_handle_generated_event(channel, &event);
break;
case FSE_AZ_EV_CODE_GLOBAL_EV:
efx_handle_global_event(channel, &event);
Expand Down Expand Up @@ -1096,7 +1114,18 @@ void efx_nic_remove_eventq(struct efx_channel *channel)

void efx_nic_generate_test_event(struct efx_channel *channel)
{
unsigned int magic = EFX_CHANNEL_MAGIC(channel);
unsigned int magic = EFX_CHANNEL_MAGIC_TEST(channel);
efx_qword_t test_event;

EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE,
FSE_AZ_EV_CODE_DRV_GEN_EV,
FSF_AZ_DRV_GEN_EV_MAGIC, magic);
efx_generate_event(channel, &test_event);
}

void efx_nic_generate_fill_event(struct efx_channel *channel)
{
unsigned int magic = EFX_CHANNEL_MAGIC_FILL(channel);
efx_qword_t test_event;

EFX_POPULATE_QWORD_2(test_event, FSF_AZ_EV_CODE,
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/sfc/nic.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ extern int efx_nic_rx_xoff_thresh, efx_nic_rx_xon_thresh;
extern int efx_nic_init_interrupt(struct efx_nic *efx);
extern void efx_nic_enable_interrupts(struct efx_nic *efx);
extern void efx_nic_generate_test_event(struct efx_channel *channel);
extern void efx_nic_generate_fill_event(struct efx_channel *channel);
extern void efx_nic_generate_interrupt(struct efx_nic *efx);
extern void efx_nic_disable_interrupts(struct efx_nic *efx);
extern void efx_nic_fini_interrupt(struct efx_nic *efx);
Expand Down
Loading

0 comments on commit ad095d1

Please sign in to comment.