* [PATCH 14/16] sfc: Change MAC promiscuity and multicast hash at the same time
From: Ben Hutchings @ 2009-11-26 2:12 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
From: Steve Hodgson <shodgson@solarflare.com>
Currently we can set multicast hash immediately (in atomic context)
but must delay setting MAC promiscuity. There is not that much
point in deferring one but not the other, and setting the multicast
hash on Siena will involve a firmware request. So process them
both in efx_mac_work().
Also, set the broadcast bit in the multicast hash in
efx_set_multicast_list(), since this is required for both Falcon and
Siena.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/efx.c | 38 ++++++++++++++++++++++++--------------
drivers/net/sfc/falcon.c | 10 +++-------
drivers/net/sfc/falcon.h | 2 +-
drivers/net/sfc/net_driver.h | 2 +-
4 files changed, 29 insertions(+), 23 deletions(-)
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 15616dd..1009d1e 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -688,11 +688,18 @@ static void efx_phy_work(struct work_struct *data)
mutex_unlock(&efx->mac_lock);
}
+/* Asynchronous work item for changing MAC promiscuity and multicast
+ * hash. Avoid a drain/rx_ingress enable by reconfiguring the current
+ * MAC directly. */
static void efx_mac_work(struct work_struct *data)
{
struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
mutex_lock(&efx->mac_lock);
+ if (efx->port_enabled) {
+ falcon_push_multicast_hash(efx);
+ efx->mac_op->reconfigure(efx);
+ }
mutex_unlock(&efx->mac_lock);
}
@@ -771,7 +778,12 @@ static void efx_start_port(struct efx_nic *efx)
mutex_lock(&efx->mac_lock);
efx->port_enabled = true;
- __efx_reconfigure_port(efx);
+
+ /* efx_mac_work() might have been scheduled after efx_stop_port(),
+ * and then cancelled by efx_flush_all() */
+ falcon_push_multicast_hash(efx);
+ efx->mac_op->reconfigure(efx);
+
mutex_unlock(&efx->mac_lock);
}
@@ -1534,16 +1546,14 @@ static void efx_set_multicast_list(struct net_device *net_dev)
struct efx_nic *efx = netdev_priv(net_dev);
struct dev_mc_list *mc_list = net_dev->mc_list;
union efx_multicast_hash *mc_hash = &efx->multicast_hash;
- bool promiscuous = !!(net_dev->flags & IFF_PROMISC);
- bool changed = (efx->promiscuous != promiscuous);
u32 crc;
int bit;
int i;
- efx->promiscuous = promiscuous;
+ efx->promiscuous = !!(net_dev->flags & IFF_PROMISC);
/* Build multicast hash table */
- if (promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
+ if (efx->promiscuous || (net_dev->flags & IFF_ALLMULTI)) {
memset(mc_hash, 0xff, sizeof(*mc_hash));
} else {
memset(mc_hash, 0x00, sizeof(*mc_hash));
@@ -1553,17 +1563,17 @@ static void efx_set_multicast_list(struct net_device *net_dev)
set_bit_le(bit, mc_hash->byte);
mc_list = mc_list->next;
}
- }
- if (!efx->port_enabled)
- /* Delay pushing settings until efx_start_port() */
- return;
-
- if (changed)
- queue_work(efx->workqueue, &efx->phy_work);
+ /* Broadcast packets go through the multicast hash filter.
+ * ether_crc_le() of the broadcast address is 0xbe2612ff
+ * so we always add bit 0xff to the mask.
+ */
+ set_bit_le(0xff, mc_hash->byte);
+ }
- /* Create and activate new global multicast hash table */
- falcon_set_multicast_hash(efx);
+ if (efx->port_enabled)
+ queue_work(efx->workqueue, &efx->mac_work);
+ /* Otherwise efx_start_port() will do this */
}
static const struct net_device_ops efx_netdev_ops = {
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index fac534a..e26043e 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -1993,7 +1993,7 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
efx_writeo(efx, ®, FR_AB_MAC_CTRL);
/* Restore the multicast hash registers. */
- falcon_set_multicast_hash(efx);
+ falcon_push_multicast_hash(efx);
/* Transmission of pause frames when RX crosses the threshold is
* covered by RX_XOFF_MAC_EN and XM_TX_CFG_REG:XM_FCNTL.
@@ -2327,15 +2327,11 @@ void falcon_remove_port(struct efx_nic *efx)
**************************************************************************
*/
-void falcon_set_multicast_hash(struct efx_nic *efx)
+void falcon_push_multicast_hash(struct efx_nic *efx)
{
union efx_multicast_hash *mc_hash = &efx->multicast_hash;
- /* Broadcast packets go through the multicast hash filter.
- * ether_crc_le() of the broadcast address is 0xbe2612ff
- * so we always add bit 0xff to the mask.
- */
- set_bit_le(0xff, mc_hash->byte);
+ WARN_ON(!mutex_is_locked(&efx->mac_lock));
efx_writeo(efx, &mc_hash->oword[0], FR_AB_MAC_MC_HASH_REG0);
efx_writeo(efx, &mc_hash->oword[1], FR_AB_MAC_MC_HASH_REG1);
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index 9ae1b6c..c70bb08 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -163,7 +163,7 @@ extern void falcon_remove_nic(struct efx_nic *efx);
extern void falcon_update_nic_stats(struct efx_nic *efx);
extern void falcon_start_nic_stats(struct efx_nic *efx);
extern void falcon_stop_nic_stats(struct efx_nic *efx);
-extern void falcon_set_multicast_hash(struct efx_nic *efx);
+extern void falcon_push_multicast_hash(struct efx_nic *efx);
extern int falcon_reset_xaui(struct efx_nic *efx);
/* Tests */
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index cc1a97b..ead1c98 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -730,7 +730,7 @@ union efx_multicast_hash {
* @multicast_hash: Multicast hash table
* @wanted_fc: Wanted flow control flags
* @phy_work: work item for dealing with PHY events
- * @mac_work: work item for dealing with MAC events
+ * @mac_work: Work item for changing MAC promiscuity and multicast hash
* @loopback_mode: Loopback status
* @loopback_modes: Supported loopback mode bitmask
* @loopback_selftest: Offline self-test private state
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 13/16] sfc: Simplify XMAC link polling
From: Ben Hutchings @ 2009-11-26 2:12 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
From: Steve Hodgson <shodgson@solarflare.com>
Only the XMAC on Falcon needs help from the driver to poll and reset
the MAC-PHY link (XAUI); GMII is a simple parallel bus and on later
NICs firmware takes care of the XAUI link. Also, an XMAC interrupt
currently schedules a work item which simply clears a flag
(efx_nic::mac_up) to be checked by the regular monitor (or the next
link reconfiguration, if that is sooner).
Rename the flag to xmac_poll_required, changing its sense. Remove the
needless indirection and just set the flag immediately. Call
falcon_xmac_poll() directly where required.
Add a new generic operation mac_op::check_fault to check the link
outside of regular monitoring, as required during self-tests.
(Note that this leaves us with an unused work item, but we will
immediately have another use for it.)
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/efx.c | 5 ----
drivers/net/sfc/falcon.c | 7 +++--
drivers/net/sfc/falcon.h | 2 +
drivers/net/sfc/falcon_boards.c | 4 +-
drivers/net/sfc/falcon_gmac.c | 8 ++++-
drivers/net/sfc/falcon_xmac.c | 50 +++++++++++++++-----------------------
drivers/net/sfc/net_driver.h | 10 +++----
drivers/net/sfc/selftest.c | 9 ++----
8 files changed, 41 insertions(+), 54 deletions(-)
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index d17cea9..15616dd 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -693,8 +693,6 @@ static void efx_mac_work(struct work_struct *data)
struct efx_nic *efx = container_of(data, struct efx_nic, mac_work);
mutex_lock(&efx->mac_lock);
- if (efx->port_enabled)
- efx->mac_op->irq(efx);
mutex_unlock(&efx->mac_lock);
}
@@ -774,7 +772,6 @@ static void efx_start_port(struct efx_nic *efx)
mutex_lock(&efx->mac_lock);
efx->port_enabled = true;
__efx_reconfigure_port(efx);
- efx->mac_op->irq(efx);
mutex_unlock(&efx->mac_lock);
}
@@ -1903,8 +1900,6 @@ void efx_port_dummy_op_set_id_led(struct efx_nic *efx, enum efx_led_mode mode)
static struct efx_mac_operations efx_dummy_mac_operations = {
.reconfigure = efx_port_dummy_op_void,
- .poll = efx_port_dummy_op_void,
- .irq = efx_port_dummy_op_void,
};
static struct efx_phy_operations efx_dummy_phy_operations = {
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index c43c5e6..fac534a 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -900,7 +900,7 @@ static void falcon_handle_global_event(struct efx_channel *channel,
if ((falcon_rev(efx) >= FALCON_REV_B0) &&
EFX_QWORD_FIELD(*event, FSF_BB_GLB_EV_XG_MGT_INTR)) {
- queue_work(efx->workqueue, &efx->mac_work);
+ efx->xmac_poll_required = true;
handled = true;
}
@@ -2251,7 +2251,7 @@ int falcon_switch_mac(struct efx_nic *efx)
EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
/* Not all macs support a mac-level link state */
- efx->mac_up = true;
+ efx->xmac_poll_required = false;
rc = falcon_reset_macs(efx);
out:
@@ -2624,7 +2624,8 @@ void falcon_monitor(struct efx_nic *efx)
falcon_sim_phy_event(efx);
}
efx->phy_op->poll(efx);
- efx->mac_op->poll(efx);
+ if (EFX_IS10G(efx))
+ falcon_poll_xmac(efx);
}
/* Zeroes out the SRAM contents. This routine must be called in
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index 05e51c2..9ae1b6c 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -209,4 +209,6 @@ extern int falcon_test_registers(struct efx_nic *efx);
extern void falcon_generate_event(struct efx_channel *channel,
efx_qword_t *event);
+extern void falcon_poll_xmac(struct efx_nic *efx);
+
#endif /* EFX_FALCON_H */
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index 72d1c78..da75095 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -380,7 +380,7 @@ static int sfe4001_check_hw(struct efx_nic *efx)
s32 status;
/* If XAUI link is up then do not monitor */
- if (EFX_WORKAROUND_7884(efx) && efx->mac_up)
+ if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
return 0;
/* Check the powered status of the PHY. Lack of power implies that
@@ -468,7 +468,7 @@ static int sfn4111t_check_hw(struct efx_nic *efx)
s32 status;
/* If XAUI link is up then do not monitor */
- if (EFX_WORKAROUND_7884(efx) && efx->mac_up)
+ if (EFX_WORKAROUND_7884(efx) && !efx->xmac_poll_required)
return 0;
/* Test LHIGH, RHIGH, FAULT, EOT and IOT alarms */
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c
index 2aeb3fc..66d499c 100644
--- a/drivers/net/sfc/falcon_gmac.c
+++ b/drivers/net/sfc/falcon_gmac.c
@@ -216,9 +216,13 @@ static void falcon_update_stats_gmac(struct efx_nic *efx)
mac_stats->rx_lt64 = mac_stats->rx_good_lt64 + mac_stats->rx_bad_lt64;
}
+static bool falcon_gmac_check_fault(struct efx_nic *efx)
+{
+ return false;
+}
+
struct efx_mac_operations falcon_gmac_operations = {
.reconfigure = falcon_reconfigure_gmac,
.update_stats = falcon_update_stats_gmac,
- .irq = efx_port_dummy_op_void,
- .poll = efx_port_dummy_op_void,
+ .check_fault = falcon_gmac_check_fault,
};
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index e57545d..784260f 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -98,7 +98,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, bool enable)
/* We can only use this interrupt to signal the negative edge of
* xaui_align [we have to poll the positive edge]. */
- if (!efx->mac_up)
+ if (efx->xmac_poll_required)
return;
/* Flush the ISR */
@@ -243,29 +243,35 @@ static void falcon_reconfigure_xgxs_core(struct efx_nic *efx)
}
-/* Try and bring the Falcon side of the Falcon-Phy XAUI link fails
- * to come back up. Bash it until it comes back up */
-static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
+/* Try to bring up the Falcon side of the Falcon-Phy XAUI link */
+static bool falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
{
- efx->mac_up = falcon_xaui_link_ok(efx);
+ bool mac_up = falcon_xaui_link_ok(efx);
if ((efx->loopback_mode == LOOPBACK_NETWORK) ||
efx_phy_mode_disabled(efx->phy_mode))
/* XAUI link is expected to be down */
- return;
+ return mac_up;
falcon_stop_nic_stats(efx);
- while (!efx->mac_up && tries) {
+ while (!mac_up && tries) {
EFX_LOG(efx, "bashing xaui\n");
falcon_reset_xaui(efx);
udelay(200);
- efx->mac_up = falcon_xaui_link_ok(efx);
+ mac_up = falcon_xaui_link_ok(efx);
--tries;
}
falcon_start_nic_stats(efx);
+
+ return mac_up;
+}
+
+static bool falcon_xmac_check_fault(struct efx_nic *efx)
+{
+ return !falcon_check_xaui_link_up(efx, 5);
}
static void falcon_reconfigure_xmac(struct efx_nic *efx)
@@ -277,7 +283,7 @@ static void falcon_reconfigure_xmac(struct efx_nic *efx)
falcon_reconfigure_mac_wrapper(efx);
- falcon_check_xaui_link_up(efx, 5);
+ efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 5);
falcon_mask_status_intr(efx, true);
}
@@ -341,35 +347,19 @@ static void falcon_update_stats_xmac(struct efx_nic *efx)
mac_stats->rx_control * 64);
}
-static void falcon_xmac_irq(struct efx_nic *efx)
-{
- /* The XGMII link has a transient fault, which indicates either:
- * - there's a transient xgmii fault
- * - falcon's end of the xaui link may need a kick
- * - the wire-side link may have gone down, but the lasi/poll()
- * hasn't noticed yet.
- *
- * We only want to even bother polling XAUI if we're confident it's
- * not (1) or (3). In both cases, the only reliable way to spot this
- * is to wait a bit. We do this here by forcing the mac link state
- * to down, and waiting for the mac poll to come round and check
- */
- efx->mac_up = false;
-}
-
-static void falcon_poll_xmac(struct efx_nic *efx)
+void falcon_poll_xmac(struct efx_nic *efx)
{
- if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up || efx->mac_up)
+ if (!EFX_WORKAROUND_5147(efx) || !efx->link_state.up ||
+ !efx->xmac_poll_required)
return;
falcon_mask_status_intr(efx, false);
- falcon_check_xaui_link_up(efx, 1);
+ efx->xmac_poll_required = !falcon_check_xaui_link_up(efx, 1);
falcon_mask_status_intr(efx, true);
}
struct efx_mac_operations falcon_xmac_operations = {
.reconfigure = falcon_reconfigure_xmac,
.update_stats = falcon_update_stats_xmac,
- .irq = falcon_xmac_irq,
- .poll = falcon_poll_xmac,
+ .check_fault = falcon_xmac_check_fault,
};
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index 262aeab..cc1a97b 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -507,14 +507,12 @@ struct efx_link_state {
* struct efx_mac_operations - Efx MAC operations table
* @reconfigure: Reconfigure MAC. Serialised by the mac_lock
* @update_stats: Update statistics
- * @irq: Hardware MAC event callback. Serialised by the mac_lock
- * @poll: Poll for hardware state. Serialised by the mac_lock
+ * @check_fault: Check fault state. True if fault present.
*/
struct efx_mac_operations {
void (*reconfigure) (struct efx_nic *efx);
void (*update_stats) (struct efx_nic *efx);
- void (*irq) (struct efx_nic *efx);
- void (*poll) (struct efx_nic *efx);
+ bool (*check_fault)(struct efx_nic *efx);
};
/**
@@ -725,7 +723,7 @@ union efx_multicast_hash {
* @phy_data: PHY private data (including PHY-specific stats)
* @mdio: PHY MDIO interface
* @phy_mode: PHY operating mode. Serialised by @mac_lock.
- * @mac_up: MAC link state
+ * @xmac_poll_required: XMAC link state needs polling
* @link_state: Current state of the link
* @n_link_state_changes: Number of times the link has changed state
* @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
@@ -810,7 +808,7 @@ struct efx_nic {
struct mdio_if_info mdio;
enum efx_phy_mode phy_mode;
- bool mac_up;
+ bool xmac_poll_required;
struct efx_link_state link_state;
unsigned int n_link_state_changes;
diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c
index 63ff295..23e646a 100644
--- a/drivers/net/sfc/selftest.c
+++ b/drivers/net/sfc/selftest.c
@@ -610,13 +610,10 @@ static int efx_test_loopbacks(struct efx_nic *efx, struct efx_self_tests *tests,
flush_workqueue(efx->workqueue);
rmb();
- /* We need both the phy and xaui links to be ok.
- * rather than relying on the falcon_xmac irq/poll
- * regime, just poll xaui directly */
+ /* We need both the PHY and MAC-PHY links to be OK */
link_up = efx->link_state.up;
- if (link_up && EFX_IS10G(efx) &&
- !falcon_xaui_link_ok(efx))
- link_up = false;
+ if (link_up)
+ link_up = !efx->mac_op->check_fault(efx);
} while ((++count < 20) && !link_up);
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 12/16] sfc: Move Falcon board/PHY/MAC monitoring code to falcon.c
From: Ben Hutchings @ 2009-11-26 2:11 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/efx.c | 11 +----------
drivers/net/sfc/falcon.c | 15 +++++++++++++++
drivers/net/sfc/falcon.h | 1 +
3 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 41ca5db..d17cea9 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1293,7 +1293,6 @@ static void efx_monitor(struct work_struct *data)
{
struct efx_nic *efx = container_of(data, struct efx_nic,
monitor_work.work);
- int rc;
EFX_TRACE(efx, "hardware monitor executing on CPU %d\n",
raw_smp_processor_id());
@@ -1305,15 +1304,7 @@ static void efx_monitor(struct work_struct *data)
goto out_requeue;
if (!efx->port_enabled)
goto out_unlock;
- rc = falcon_board(efx)->type->monitor(efx);
- if (rc) {
- EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
- (rc == -ERANGE) ? "reported fault" : "failed");
- efx->phy_mode |= PHY_MODE_LOW_POWER;
- falcon_sim_phy_event(efx);
- }
- efx->phy_op->poll(efx);
- efx->mac_op->poll(efx);
+ falcon_monitor(efx);
out_unlock:
mutex_unlock(&efx->mac_lock);
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 3ab2daf..c43c5e6 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -2612,6 +2612,21 @@ fail5:
return rc;
}
+void falcon_monitor(struct efx_nic *efx)
+{
+ int rc;
+
+ rc = falcon_board(efx)->type->monitor(efx);
+ if (rc) {
+ EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
+ (rc == -ERANGE) ? "reported fault" : "failed");
+ efx->phy_mode |= PHY_MODE_LOW_POWER;
+ falcon_sim_phy_event(efx);
+ }
+ efx->phy_op->poll(efx);
+ efx->mac_op->poll(efx);
+}
+
/* Zeroes out the SRAM contents. This routine must be called in
* process context and is allowed to sleep.
*/
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index 61fab0a..05e51c2 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -158,6 +158,7 @@ extern int falcon_probe_nic(struct efx_nic *efx);
extern int falcon_init_nic(struct efx_nic *efx);
extern int falcon_flush_queues(struct efx_nic *efx);
extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method);
+extern void falcon_monitor(struct efx_nic *efx);
extern void falcon_remove_nic(struct efx_nic *efx);
extern void falcon_update_nic_stats(struct efx_nic *efx);
extern void falcon_start_nic_stats(struct efx_nic *efx);
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 11/16] sfc: Split MAC stats DMA initiation and completion
From: Ben Hutchings @ 2009-11-26 2:11 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
From: Steve Hodgson <shodgson@solarflare.com>
Currently we initiate MAC stats DMA and busy-wait for completion when
stats are requested. We can improve on this with a periodic timer to
initiate and poll for stats, and opportunistically poll when stats are
requested.
Since efx_nic::stats_disable_count and efx_stats_{disable,enable}()
are Falcon-specific, rename them and move them accordingly.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/efx.c | 48 ++++----------
drivers/net/sfc/efx.h | 2 -
drivers/net/sfc/falcon.c | 131 ++++++++++++++++++++++++++++++---------
drivers/net/sfc/falcon.h | 12 +++-
drivers/net/sfc/falcon_boards.c | 10 ++--
drivers/net/sfc/falcon_gmac.c | 5 --
drivers/net/sfc/falcon_xmac.c | 13 +++--
drivers/net/sfc/net_driver.h | 2 -
drivers/net/sfc/tenxpress.c | 4 +-
9 files changed, 139 insertions(+), 88 deletions(-)
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 155aa1c..41ca5db 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -637,6 +637,7 @@ void __efx_reconfigure_port(struct efx_nic *efx)
netif_addr_unlock_bh(efx->net_dev);
}
+ falcon_stop_nic_stats(efx);
falcon_deconfigure_mac_wrapper(efx);
/* Reconfigure the PHY, disabling transmit in mac level loopback. */
@@ -651,6 +652,8 @@ void __efx_reconfigure_port(struct efx_nic *efx)
efx->mac_op->reconfigure(efx);
+ falcon_start_nic_stats(efx);
+
/* Inform kernel of loss/gain of carrier */
efx_link_status_changed(efx);
return;
@@ -749,7 +752,6 @@ static int efx_init_port(struct efx_nic *efx)
efx->mac_op->reconfigure(efx);
efx->port_initialized = true;
- efx_stats_enable(efx);
mutex_unlock(&efx->mac_lock);
return 0;
@@ -802,7 +804,6 @@ static void efx_fini_port(struct efx_nic *efx)
if (!efx->port_initialized)
return;
- efx_stats_disable(efx);
efx->phy_op->fini(efx);
efx->port_initialized = false;
@@ -1158,6 +1159,8 @@ static void efx_start_all(struct efx_nic *efx)
if (efx->state == STATE_RUNNING)
queue_delayed_work(efx->workqueue, &efx->monitor_work,
efx_monitor_interval);
+
+ falcon_start_nic_stats(efx);
}
/* Flush all delayed work. Should only be called when no more delayed work
@@ -1195,6 +1198,8 @@ static void efx_stop_all(struct efx_nic *efx)
if (!efx->port_enabled)
return;
+ falcon_stop_nic_stats(efx);
+
/* Disable interrupts and wait for ISR to complete */
falcon_disable_interrupts(efx);
if (efx->legacy_irq)
@@ -1438,20 +1443,6 @@ static int efx_net_stop(struct net_device *net_dev)
return 0;
}
-void efx_stats_disable(struct efx_nic *efx)
-{
- spin_lock(&efx->stats_lock);
- ++efx->stats_disable_count;
- spin_unlock(&efx->stats_lock);
-}
-
-void efx_stats_enable(struct efx_nic *efx)
-{
- spin_lock(&efx->stats_lock);
- --efx->stats_disable_count;
- spin_unlock(&efx->stats_lock);
-}
-
/* Context: process, dev_base_lock or RTNL held, non-blocking. */
static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
{
@@ -1459,17 +1450,9 @@ static struct net_device_stats *efx_net_stats(struct net_device *net_dev)
struct efx_mac_stats *mac_stats = &efx->mac_stats;
struct net_device_stats *stats = &net_dev->stats;
- /* Update stats if possible, but do not wait if another thread
- * is updating them or if MAC stats fetches are temporarily
- * disabled; slightly stale stats are acceptable.
- */
- if (!spin_trylock(&efx->stats_lock))
- return stats;
- if (!efx->stats_disable_count) {
- efx->mac_op->update_stats(efx);
- falcon_update_nic_stats(efx);
- }
- spin_unlock(&efx->stats_lock);
+ spin_lock_bh(&efx->stats_lock);
+ falcon_update_nic_stats(efx);
+ spin_unlock_bh(&efx->stats_lock);
stats->rx_packets = mac_stats->rx_packets;
stats->tx_packets = mac_stats->tx_packets;
@@ -1726,7 +1709,6 @@ void efx_reset_down(struct efx_nic *efx, enum reset_type method,
{
EFX_ASSERT_RESET_SERIALISED(efx);
- efx_stats_disable(efx);
efx_stop_all(efx);
mutex_lock(&efx->mac_lock);
mutex_lock(&efx->spi_lock);
@@ -1776,10 +1758,8 @@ int efx_reset_up(struct efx_nic *efx, enum reset_type method,
mutex_unlock(&efx->spi_lock);
mutex_unlock(&efx->mac_lock);
- if (ok) {
+ if (ok)
efx_start_all(efx);
- efx_stats_enable(efx);
- }
return rc;
}
@@ -1977,7 +1957,6 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
efx->rx_checksum_enabled = true;
spin_lock_init(&efx->netif_stop_lock);
spin_lock_init(&efx->stats_lock);
- efx->stats_disable_count = 1;
mutex_init(&efx->mac_lock);
efx->mac_op = &efx_dummy_mac_operations;
efx->phy_op = &efx_dummy_phy_operations;
@@ -2219,9 +2198,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
goto fail4;
}
- /* Switch to the running state before we expose the device to
- * the OS. This is to ensure that the initial gathering of
- * MAC stats succeeds. */
+ /* Switch to the running state before we expose the device to the OS,
+ * so that dev_open()|efx_start_all() will actually start the device */
efx->state = STATE_RUNNING;
rc = efx_register_netdev(efx);
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index 7acf821..01b93f9 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -60,8 +60,6 @@ extern void efx_process_channel_now(struct efx_channel *channel);
#define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1)
/* Ports */
-extern void efx_stats_disable(struct efx_nic *efx);
-extern void efx_stats_enable(struct efx_nic *efx);
extern void efx_reconfigure_port(struct efx_nic *efx);
extern void __efx_reconfigure_port(struct efx_nic *efx);
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 9eec885..3ab2daf 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -36,8 +36,6 @@
**************************************************************************
*/
-static int disable_dma_stats;
-
/* This is set to 16 for a good reason. In summary, if larger than
* 16, the descriptor cache holds more than a default socket
* buffer's worth of packets (for UDP we can only have at most one
@@ -1890,7 +1888,7 @@ static int falcon_reset_macs(struct efx_nic *efx)
/* MAC stats will fail whilst the TX fifo is draining. Serialise
* the drain sequence with the statistics fetch */
- efx_stats_disable(efx);
+ falcon_stop_nic_stats(efx);
efx_reado(efx, ®, FR_AB_MAC_CTRL);
EFX_SET_OWORD_FIELD(reg, FRF_BB_TXFIFO_DRAIN_EN, 1);
@@ -1920,13 +1918,13 @@ static int falcon_reset_macs(struct efx_nic *efx)
udelay(10);
}
- efx_stats_enable(efx);
-
/* If we've reset the EM block and the link is up, then
* we'll have to kick the XAUI link so the PHY can recover */
if (efx->link_state.up && EFX_IS10G(efx) && EFX_WORKAROUND_5147(efx))
falcon_reset_xaui(efx);
+ falcon_start_nic_stats(efx);
+
return 0;
}
@@ -2010,25 +2008,19 @@ void falcon_reconfigure_mac_wrapper(struct efx_nic *efx)
efx_writeo(efx, ®, FR_AZ_RX_CFG);
}
-int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
+static void falcon_stats_request(struct efx_nic *efx)
{
+ struct falcon_nic_data *nic_data = efx->nic_data;
efx_oword_t reg;
- u32 *dma_done;
- int i;
- if (disable_dma_stats)
- return 0;
+ WARN_ON(nic_data->stats_pending);
+ WARN_ON(nic_data->stats_disable_count);
- /* Statistics fetch will fail if the MAC is in TX drain */
- if (falcon_rev(efx) >= FALCON_REV_B0) {
- efx_oword_t temp;
- efx_reado(efx, &temp, FR_AB_MAC_CTRL);
- if (EFX_OWORD_FIELD(temp, FRF_BB_TXFIFO_DRAIN_EN))
- return 0;
- }
+ if (nic_data->stats_dma_done == NULL)
+ return; /* no mac selected */
- dma_done = (efx->stats_buffer.addr + done_offset);
- *dma_done = FALCON_STATS_NOT_DONE;
+ *nic_data->stats_dma_done = FALCON_STATS_NOT_DONE;
+ nic_data->stats_pending = true;
wmb(); /* ensure done flag is clear */
/* Initiate DMA transfer of stats */
@@ -2038,17 +2030,37 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
efx->stats_buffer.dma_addr);
efx_writeo(efx, ®, FR_AB_MAC_STAT_DMA);
- /* Wait for transfer to complete */
- for (i = 0; i < 400; i++) {
- if (*(volatile u32 *)dma_done == FALCON_STATS_DONE) {
- rmb(); /* Ensure the stats are valid. */
- return 0;
- }
- udelay(10);
+ mod_timer(&nic_data->stats_timer, round_jiffies_up(jiffies + HZ / 2));
+}
+
+static void falcon_stats_complete(struct efx_nic *efx)
+{
+ struct falcon_nic_data *nic_data = efx->nic_data;
+
+ if (!nic_data->stats_pending)
+ return;
+
+ nic_data->stats_pending = 0;
+ if (*nic_data->stats_dma_done == FALCON_STATS_DONE) {
+ rmb(); /* read the done flag before the stats */
+ efx->mac_op->update_stats(efx);
+ } else {
+ EFX_ERR(efx, "timed out waiting for statistics\n");
}
+}
- EFX_ERR(efx, "timed out waiting for statistics\n");
- return -ETIMEDOUT;
+static void falcon_stats_timer_func(unsigned long context)
+{
+ struct efx_nic *efx = (struct efx_nic *)context;
+ struct falcon_nic_data *nic_data = efx->nic_data;
+
+ spin_lock(&efx->stats_lock);
+
+ falcon_stats_complete(efx);
+ if (nic_data->stats_disable_count == 0)
+ falcon_stats_request(efx);
+
+ spin_unlock(&efx->stats_lock);
}
/**************************************************************************
@@ -2206,10 +2218,12 @@ static void falcon_clock_mac(struct efx_nic *efx)
int falcon_switch_mac(struct efx_nic *efx)
{
struct efx_mac_operations *old_mac_op = efx->mac_op;
+ struct falcon_nic_data *nic_data = efx->nic_data;
+ unsigned int stats_done_offset;
int rc = 0;
/* Don't try to fetch MAC stats while we're switching MACs */
- efx_stats_disable(efx);
+ falcon_stop_nic_stats(efx);
/* Internal loopbacks override the phy speed setting */
if (efx->loopback_mode == LOOPBACK_GMAC) {
@@ -2224,6 +2238,12 @@ int falcon_switch_mac(struct efx_nic *efx)
efx->mac_op = (EFX_IS10G(efx) ?
&falcon_xmac_operations : &falcon_gmac_operations);
+ if (EFX_IS10G(efx))
+ stats_done_offset = XgDmaDone_offset;
+ else
+ stats_done_offset = GDmaDone_offset;
+ nic_data->stats_dma_done = efx->stats_buffer.addr + stats_done_offset;
+
if (old_mac_op == efx->mac_op)
goto out;
@@ -2235,7 +2255,7 @@ int falcon_switch_mac(struct efx_nic *efx)
rc = falcon_reset_macs(efx);
out:
- efx_stats_enable(efx);
+ falcon_start_nic_stats(efx);
return rc;
}
@@ -2900,6 +2920,10 @@ int falcon_probe_nic(struct efx_nic *efx)
goto fail6;
}
+ nic_data->stats_disable_count = 1;
+ setup_timer(&nic_data->stats_timer, &falcon_stats_timer_func,
+ (unsigned long)efx);
+
return 0;
fail6:
@@ -3125,11 +3149,58 @@ void falcon_remove_nic(struct efx_nic *efx)
void falcon_update_nic_stats(struct efx_nic *efx)
{
+ struct falcon_nic_data *nic_data = efx->nic_data;
efx_oword_t cnt;
+ if (nic_data->stats_disable_count)
+ return;
+
efx_reado(efx, &cnt, FR_AZ_RX_NODESC_DROP);
efx->n_rx_nodesc_drop_cnt +=
EFX_OWORD_FIELD(cnt, FRF_AB_RX_NODESC_DROP_CNT);
+
+ if (nic_data->stats_pending &&
+ *nic_data->stats_dma_done == FALCON_STATS_DONE) {
+ nic_data->stats_pending = false;
+ rmb(); /* read the done flag before the stats */
+ efx->mac_op->update_stats(efx);
+ }
+}
+
+void falcon_start_nic_stats(struct efx_nic *efx)
+{
+ struct falcon_nic_data *nic_data = efx->nic_data;
+
+ spin_lock_bh(&efx->stats_lock);
+ if (--nic_data->stats_disable_count == 0)
+ falcon_stats_request(efx);
+ spin_unlock_bh(&efx->stats_lock);
+}
+
+void falcon_stop_nic_stats(struct efx_nic *efx)
+{
+ struct falcon_nic_data *nic_data = efx->nic_data;
+ int i;
+
+ might_sleep();
+
+ spin_lock_bh(&efx->stats_lock);
+ ++nic_data->stats_disable_count;
+ spin_unlock_bh(&efx->stats_lock);
+
+ del_timer_sync(&nic_data->stats_timer);
+
+ /* Wait enough time for the most recent transfer to
+ * complete. */
+ for (i = 0; i < 4 && nic_data->stats_pending; i++) {
+ if (*nic_data->stats_dma_done == FALCON_STATS_DONE)
+ break;
+ msleep(1);
+ }
+
+ spin_lock_bh(&efx->stats_lock);
+ falcon_stats_complete(efx);
+ spin_unlock_bh(&efx->stats_lock);
}
/**************************************************************************
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index b331889..61fab0a 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -75,10 +75,18 @@ struct falcon_board {
* struct falcon_nic_data - Falcon NIC state
* @pci_dev2: Secondary function of Falcon A
* @board: Board state and functions
+ * @stats_disable_count: Nest count for disabling statistics fetches
+ * @stats_pending: Is there a pending DMA of MAC statistics.
+ * @stats_timer: A timer for regularly fetching MAC statistics.
+ * @stats_dma_done: Pointer to the flag which indicates DMA completion.
*/
struct falcon_nic_data {
struct pci_dev *pci_dev2;
struct falcon_board board;
+ unsigned int stats_disable_count;
+ bool stats_pending;
+ struct timer_list stats_timer;
+ u32 *stats_dma_done;
};
static inline struct falcon_board *falcon_board(struct efx_nic *efx)
@@ -128,8 +136,6 @@ extern void falcon_remove_port(struct efx_nic *efx);
/* MAC/PHY */
extern int falcon_switch_mac(struct efx_nic *efx);
extern bool falcon_xaui_link_ok(struct efx_nic *efx);
-extern int falcon_dma_stats(struct efx_nic *efx,
- unsigned int done_offset);
extern void falcon_drain_tx_fifo(struct efx_nic *efx);
extern void falcon_deconfigure_mac_wrapper(struct efx_nic *efx);
extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx);
@@ -154,6 +160,8 @@ extern int falcon_flush_queues(struct efx_nic *efx);
extern int falcon_reset_hw(struct efx_nic *efx, enum reset_type method);
extern void falcon_remove_nic(struct efx_nic *efx);
extern void falcon_update_nic_stats(struct efx_nic *efx);
+extern void falcon_start_nic_stats(struct efx_nic *efx);
+extern void falcon_stop_nic_stats(struct efx_nic *efx);
extern void falcon_set_multicast_hash(struct efx_nic *efx);
extern int falcon_reset_xaui(struct efx_nic *efx);
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index ac1258e..72d1c78 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -347,14 +347,14 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
* MAC stats accordingly. */
efx->phy_mode = new_mode;
if (new_mode & PHY_MODE_SPECIAL)
- efx_stats_disable(efx);
+ falcon_stop_nic_stats(efx);
if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001)
err = sfe4001_poweron(efx);
else
err = sfn4111t_reset(efx);
efx_reconfigure_port(efx);
if (!(new_mode & PHY_MODE_SPECIAL))
- efx_stats_enable(efx);
+ falcon_start_nic_stats(efx);
}
rtnl_unlock();
@@ -441,7 +441,7 @@ static int sfe4001_init(struct efx_nic *efx)
if (efx->phy_mode & PHY_MODE_SPECIAL) {
/* PHY won't generate a 156.25 MHz clock and MAC stats fetch
* will fail. */
- efx_stats_disable(efx);
+ falcon_stop_nic_stats(efx);
}
rc = sfe4001_poweron(efx);
if (rc)
@@ -504,7 +504,7 @@ static void sfn4111t_init_phy(struct efx_nic *efx)
return;
efx->phy_mode = PHY_MODE_SPECIAL;
- efx_stats_disable(efx);
+ falcon_stop_nic_stats(efx);
}
sfn4111t_reset(efx);
@@ -531,7 +531,7 @@ static int sfn4111t_init(struct efx_nic *efx)
if (efx->phy_mode & PHY_MODE_SPECIAL)
/* PHY may not generate a 156.25 MHz clock and MAC
* stats fetch will fail. */
- efx_stats_disable(efx);
+ falcon_stop_nic_stats(efx);
return 0;
diff --git a/drivers/net/sfc/falcon_gmac.c b/drivers/net/sfc/falcon_gmac.c
index 967f3fb..2aeb3fc 100644
--- a/drivers/net/sfc/falcon_gmac.c
+++ b/drivers/net/sfc/falcon_gmac.c
@@ -130,11 +130,6 @@ static void falcon_update_stats_gmac(struct efx_nic *efx)
struct efx_mac_stats *mac_stats = &efx->mac_stats;
unsigned long old_rx_pause, old_tx_pause;
unsigned long new_rx_pause, new_tx_pause;
- int rc;
-
- rc = falcon_dma_stats(efx, GDmaDone_offset);
- if (rc)
- return;
/* Pause frames are erroneously counted as errors (SFC bug 3269) */
old_rx_pause = mac_stats->rx_pause;
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index cf24513..e57545d 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -60,9 +60,13 @@ static void falcon_setup_xaui(struct efx_nic *efx)
int falcon_reset_xaui(struct efx_nic *efx)
{
+ struct falcon_nic_data *nic_data = efx->nic_data;
efx_oword_t reg;
int count;
+ /* Don't fetch MAC statistics over an XMAC reset */
+ WARN_ON(nic_data->stats_disable_count == 0);
+
/* Start reset sequence */
EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1);
efx_writeo(efx, ®, FR_AB_XX_PWR_RST);
@@ -250,6 +254,8 @@ static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
/* XAUI link is expected to be down */
return;
+ falcon_stop_nic_stats(efx);
+
while (!efx->mac_up && tries) {
EFX_LOG(efx, "bashing xaui\n");
falcon_reset_xaui(efx);
@@ -258,6 +264,8 @@ static void falcon_check_xaui_link_up(struct efx_nic *efx, int tries)
efx->mac_up = falcon_xaui_link_ok(efx);
--tries;
}
+
+ falcon_start_nic_stats(efx);
}
static void falcon_reconfigure_xmac(struct efx_nic *efx)
@@ -276,11 +284,6 @@ static void falcon_reconfigure_xmac(struct efx_nic *efx)
static void falcon_update_stats_xmac(struct efx_nic *efx)
{
struct efx_mac_stats *mac_stats = &efx->mac_stats;
- int rc;
-
- rc = falcon_dma_stats(efx, XgDmaDone_offset);
- if (rc)
- return;
/* Update MAC stats from DMAed values */
FALCON_STAT(efx, XgRxOctets, rx_bytes);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index d0755ab..262aeab 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -717,7 +717,6 @@ union efx_multicast_hash {
* &struct net_device_stats.
* @stats_buffer: DMA buffer for statistics
* @stats_lock: Statistics update lock. Serialises statistics fetches
- * @stats_disable_count: Nest count for disabling statistics fetches
* @mac_op: MAC interface
* @mac_address: Permanent MAC address
* @phy_type: PHY type
@@ -799,7 +798,6 @@ struct efx_nic {
struct efx_mac_stats mac_stats;
struct efx_buffer stats_buffer;
spinlock_t stats_lock;
- unsigned int stats_disable_count;
struct efx_mac_operations *mac_op;
unsigned char mac_address[ETH_ALEN];
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index a95402d..e6232fe 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -374,7 +374,7 @@ static int tenxpress_special_reset(struct efx_nic *efx)
/* The XGMAC clock is driven from the SFC7101/SFT9001 312MHz clock, so
* a special software reset can glitch the XGMAC sufficiently for stats
* requests to fail. */
- efx_stats_disable(efx);
+ falcon_stop_nic_stats(efx);
/* Initiate reset */
reg = efx_mdio_read(efx, MDIO_MMD_PMAPMD, PMA_PMD_XCONTROL_REG);
@@ -396,7 +396,7 @@ static int tenxpress_special_reset(struct efx_nic *efx)
/* Wait for the XGXS state machine to churn */
mdelay(10);
out:
- efx_stats_enable(efx);
+ falcon_start_nic_stats(efx);
return rc;
}
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 10/16] sfc: Hold MAC lock for longer in efx_init_port()
From: Ben Hutchings @ 2009-11-26 2:11 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Although efx_init_port() is only called at probe time and so cannot
race with port reconfiguration, most of the functions it calls can
expect to be called with the MAC lock held.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/efx.c | 14 +++++++++-----
1 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 4ebad61..155aa1c 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -737,23 +737,27 @@ static int efx_init_port(struct efx_nic *efx)
EFX_LOG(efx, "init port\n");
+ mutex_lock(&efx->mac_lock);
+
rc = efx->phy_op->init(efx);
if (rc)
- return rc;
- mutex_lock(&efx->mac_lock);
+ goto fail1;
efx->phy_op->reconfigure(efx);
rc = falcon_switch_mac(efx);
- mutex_unlock(&efx->mac_lock);
if (rc)
- goto fail;
+ goto fail2;
efx->mac_op->reconfigure(efx);
efx->port_initialized = true;
efx_stats_enable(efx);
+
+ mutex_unlock(&efx->mac_lock);
return 0;
-fail:
+fail2:
efx->phy_op->fini(efx);
+fail1:
+ mutex_unlock(&efx->mac_lock);
return rc;
}
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 09/16] sfc: Only switch Falcon MAC clocks as necessary
From: Ben Hutchings @ 2009-11-26 2:11 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
From: Steve Hodgson <shodgson@solarflare.com>
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/falcon.c | 42 +++++++++++++++++++++++++-----------------
1 files changed, 25 insertions(+), 17 deletions(-)
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index e1b9ce3..9eec885 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -2183,11 +2183,29 @@ static int falcon_mdio_read(struct net_device *net_dev,
return rc;
}
+static void falcon_clock_mac(struct efx_nic *efx)
+{
+ unsigned strap_val;
+ efx_oword_t nic_stat;
+
+ /* Configure the NIC generated MAC clock correctly */
+ efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
+ strap_val = EFX_IS10G(efx) ? 5 : 3;
+ if (falcon_rev(efx) >= FALCON_REV_B0) {
+ EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP_EN, 1);
+ EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP, strap_val);
+ efx_writeo(efx, &nic_stat, FR_AB_NIC_STAT);
+ } else {
+ /* Falcon A1 does not support 1G/10G speed switching
+ * and must not be used with a PHY that does. */
+ BUG_ON(EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_PINS) !=
+ strap_val);
+ }
+}
+
int falcon_switch_mac(struct efx_nic *efx)
{
struct efx_mac_operations *old_mac_op = efx->mac_op;
- efx_oword_t nic_stat;
- unsigned strap_val;
int rc = 0;
/* Don't try to fetch MAC stats while we're switching MACs */
@@ -2206,24 +2224,11 @@ int falcon_switch_mac(struct efx_nic *efx)
efx->mac_op = (EFX_IS10G(efx) ?
&falcon_xmac_operations : &falcon_gmac_operations);
- /* Always push the NIC_STAT_REG setting even if the mac hasn't
- * changed, because this function is run post online reset */
- efx_reado(efx, &nic_stat, FR_AB_NIC_STAT);
- strap_val = EFX_IS10G(efx) ? 5 : 3;
- if (falcon_rev(efx) >= FALCON_REV_B0) {
- EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP_EN, 1);
- EFX_SET_OWORD_FIELD(nic_stat, FRF_BB_EE_STRAP, strap_val);
- efx_writeo(efx, &nic_stat, FR_AB_NIC_STAT);
- } else {
- /* Falcon A1 does not support 1G/10G speed switching
- * and must not be used with a PHY that does. */
- BUG_ON(EFX_OWORD_FIELD(nic_stat, FRF_AB_STRAP_PINS) !=
- strap_val);
- }
-
if (old_mac_op == efx->mac_op)
goto out;
+ falcon_clock_mac(efx);
+
EFX_LOG(efx, "selected %cMAC\n", EFX_IS10G(efx) ? 'X' : 'G');
/* Not all macs support a mac-level link state */
efx->mac_up = true;
@@ -2982,6 +2987,9 @@ int falcon_init_nic(struct efx_nic *efx)
efx_writeo(efx, &temp, FR_AB_GPIO_CTL);
}
+ /* Select the correct MAC */
+ falcon_clock_mac(efx);
+
rc = falcon_reset_sram(efx);
if (rc)
return rc;
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 08/16] sfc: Remove unused function efx_flush_queues()
From: Ben Hutchings @ 2009-11-26 2:10 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/efx.c | 13 -------------
drivers/net/sfc/efx.h | 1 -
2 files changed, 0 insertions(+), 14 deletions(-)
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index dc85efa..4ebad61 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1237,19 +1237,6 @@ static void efx_remove_all(struct efx_nic *efx)
efx_remove_nic(efx);
}
-/* A convinience function to safely flush all the queues */
-void efx_flush_queues(struct efx_nic *efx)
-{
- EFX_ASSERT_RESET_SERIALISED(efx);
-
- efx_stop_all(efx);
-
- efx_fini_channels(efx);
- efx_init_channels(efx);
-
- efx_start_all(efx);
-}
-
/**************************************************************************
*
* Interrupt moderation
diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h
index 3497b03..7acf821 100644
--- a/drivers/net/sfc/efx.h
+++ b/drivers/net/sfc/efx.h
@@ -56,7 +56,6 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue, int delay);
/* Channels */
extern void efx_process_channel_now(struct efx_channel *channel);
-extern void efx_flush_queues(struct efx_nic *efx);
#define EFX_EVQ_SIZE 4096
#define EFX_EVQ_MASK (EFX_EVQ_SIZE - 1)
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 07/16] sfc: Fix bugs in RX queue flushing
From: Ben Hutchings @ 2009-11-26 2:09 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Avoid overrunning the hardware limit of 4 concurrent RX queue flushes.
Expand the queue flush state to support this. Make similar changes to
TX flushing to keep the code symmetric.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/falcon.c | 103 ++++++++++++++++++++++++++----------------
drivers/net/sfc/net_driver.h | 11 ++++-
2 files changed, 73 insertions(+), 41 deletions(-)
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 2f1f1fc..e1b9ce3 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -109,6 +109,9 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
/* Size and alignment of special buffers (4KB) */
#define FALCON_BUF_SIZE 4096
+/* Depth of RX flush request fifo */
+#define FALCON_RX_FLUSH_COUNT 4
+
#define FALCON_IS_DUAL_FUNC(efx) \
(falcon_rev(efx) < FALCON_REV_B0)
@@ -426,7 +429,7 @@ void falcon_init_tx(struct efx_tx_queue *tx_queue)
efx_oword_t tx_desc_ptr;
struct efx_nic *efx = tx_queue->efx;
- tx_queue->flushed = false;
+ tx_queue->flushed = FLUSH_NONE;
/* Pin TX descriptor ring */
falcon_init_special_buffer(efx, &tx_queue->txd);
@@ -476,6 +479,8 @@ static void falcon_flush_tx_queue(struct efx_tx_queue *tx_queue)
struct efx_nic *efx = tx_queue->efx;
efx_oword_t tx_flush_descq;
+ tx_queue->flushed = FLUSH_PENDING;
+
/* Post a flush command */
EFX_POPULATE_OWORD_2(tx_flush_descq,
FRF_AZ_TX_FLUSH_DESCQ_CMD, 1,
@@ -489,7 +494,7 @@ void falcon_fini_tx(struct efx_tx_queue *tx_queue)
efx_oword_t tx_desc_ptr;
/* The queue should have been flushed */
- WARN_ON(!tx_queue->flushed);
+ WARN_ON(tx_queue->flushed != FLUSH_DONE);
/* Remove TX descriptor ring from card */
EFX_ZERO_OWORD(tx_desc_ptr);
@@ -578,7 +583,7 @@ void falcon_init_rx(struct efx_rx_queue *rx_queue)
rx_queue->queue, rx_queue->rxd.index,
rx_queue->rxd.index + rx_queue->rxd.entries - 1);
- rx_queue->flushed = false;
+ rx_queue->flushed = FLUSH_NONE;
/* Pin RX descriptor ring */
falcon_init_special_buffer(efx, &rx_queue->rxd);
@@ -607,6 +612,8 @@ static void falcon_flush_rx_queue(struct efx_rx_queue *rx_queue)
struct efx_nic *efx = rx_queue->efx;
efx_oword_t rx_flush_descq;
+ rx_queue->flushed = FLUSH_PENDING;
+
/* Post a flush command */
EFX_POPULATE_OWORD_2(rx_flush_descq,
FRF_AZ_RX_FLUSH_DESCQ_CMD, 1,
@@ -620,7 +627,7 @@ void falcon_fini_rx(struct efx_rx_queue *rx_queue)
struct efx_nic *efx = rx_queue->efx;
/* The queue should already have been flushed */
- WARN_ON(!rx_queue->flushed);
+ WARN_ON(rx_queue->flushed != FLUSH_DONE);
/* Remove RX descriptor ring from card */
EFX_ZERO_OWORD(rx_desc_ptr);
@@ -1181,7 +1188,7 @@ static void falcon_poll_flush_events(struct efx_nic *efx)
FSF_AZ_DRIVER_EV_SUBDATA);
if (ev_queue < EFX_TX_QUEUE_COUNT) {
tx_queue = efx->tx_queue + ev_queue;
- tx_queue->flushed = true;
+ tx_queue->flushed = FLUSH_DONE;
}
} else if (ev_code == FSE_AZ_EV_CODE_DRIVER_EV &&
ev_sub_code == FSE_AZ_RX_DESCQ_FLS_DONE_EV) {
@@ -1191,17 +1198,29 @@ static void falcon_poll_flush_events(struct efx_nic *efx)
*event, FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL);
if (ev_queue < efx->n_rx_queues) {
rx_queue = efx->rx_queue + ev_queue;
-
- /* retry the rx flush */
- if (ev_failed)
- falcon_flush_rx_queue(rx_queue);
- else
- rx_queue->flushed = true;
+ rx_queue->flushed =
+ ev_failed ? FLUSH_FAILED : FLUSH_DONE;
}
}
+ /* We're about to destroy the queue anyway, so
+ * it's ok to throw away every non-flush event */
+ EFX_SET_QWORD(*event);
+
read_ptr = (read_ptr + 1) & EFX_EVQ_MASK;
} while (read_ptr != end_ptr);
+
+ channel->eventq_read_ptr = read_ptr;
+}
+
+static void falcon_prepare_flush(struct efx_nic *efx)
+{
+ falcon_deconfigure_mac_wrapper(efx);
+
+ /* Wait for the tx and rx fifo's to get to the next packet boundary
+ * (~1ms without back-pressure), then to drain the remainder of the
+ * fifo's at data path speeds (negligible), with a healthy margin. */
+ msleep(10);
}
/* Handle tx and rx flushes at the same time, since they run in
@@ -1211,50 +1230,56 @@ int falcon_flush_queues(struct efx_nic *efx)
{
struct efx_rx_queue *rx_queue;
struct efx_tx_queue *tx_queue;
- int i;
- bool outstanding;
+ int i, tx_pending, rx_pending;
- /* Issue flush requests */
- efx_for_each_tx_queue(tx_queue, efx) {
- tx_queue->flushed = false;
+ falcon_prepare_flush(efx);
+
+ /* Flush all tx queues in parallel */
+ efx_for_each_tx_queue(tx_queue, efx)
falcon_flush_tx_queue(tx_queue);
- }
- efx_for_each_rx_queue(rx_queue, efx) {
- rx_queue->flushed = false;
- falcon_flush_rx_queue(rx_queue);
- }
- /* Poll the evq looking for flush completions. Since we're not pushing
- * any more rx or tx descriptors at this point, we're in no danger of
- * overflowing the evq whilst we wait */
+ /* The hardware supports four concurrent rx flushes, each of which may
+ * need to be retried if there is an outstanding descriptor fetch */
for (i = 0; i < FALCON_FLUSH_POLL_COUNT; ++i) {
- msleep(FALCON_FLUSH_INTERVAL);
- falcon_poll_flush_events(efx);
+ rx_pending = tx_pending = 0;
+ efx_for_each_rx_queue(rx_queue, efx) {
+ if (rx_queue->flushed == FLUSH_PENDING)
+ ++rx_pending;
+ }
+ efx_for_each_rx_queue(rx_queue, efx) {
+ if (rx_pending == FALCON_RX_FLUSH_COUNT)
+ break;
+ if (rx_queue->flushed == FLUSH_FAILED ||
+ rx_queue->flushed == FLUSH_NONE) {
+ falcon_flush_rx_queue(rx_queue);
+ ++rx_pending;
+ }
+ }
+ efx_for_each_tx_queue(tx_queue, efx) {
+ if (tx_queue->flushed != FLUSH_DONE)
+ ++tx_pending;
+ }
- /* Check if every queue has been succesfully flushed */
- outstanding = false;
- efx_for_each_tx_queue(tx_queue, efx)
- outstanding |= !tx_queue->flushed;
- efx_for_each_rx_queue(rx_queue, efx)
- outstanding |= !rx_queue->flushed;
- if (!outstanding)
+ if (rx_pending == 0 && tx_pending == 0)
return 0;
+
+ msleep(FALCON_FLUSH_INTERVAL);
+ falcon_poll_flush_events(efx);
}
/* Mark the queues as all flushed. We're going to return failure
- * leading to a reset, or fake up success anyway. "flushed" now
- * indicates that we tried to flush. */
+ * leading to a reset, or fake up success anyway */
efx_for_each_tx_queue(tx_queue, efx) {
- if (!tx_queue->flushed)
+ if (tx_queue->flushed != FLUSH_DONE)
EFX_ERR(efx, "tx queue %d flush command timed out\n",
tx_queue->queue);
- tx_queue->flushed = true;
+ tx_queue->flushed = FLUSH_DONE;
}
efx_for_each_rx_queue(rx_queue, efx) {
- if (!rx_queue->flushed)
+ if (rx_queue->flushed != FLUSH_DONE)
EFX_ERR(efx, "rx queue %d flush command timed out\n",
rx_queue->queue);
- rx_queue->flushed = true;
+ rx_queue->flushed = FLUSH_DONE;
}
if (EFX_WORKAROUND_7803(efx))
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index ac808d5..d0755ab 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -113,6 +113,13 @@ struct efx_special_buffer {
int entries;
};
+enum efx_flush_state {
+ FLUSH_NONE,
+ FLUSH_PENDING,
+ FLUSH_FAILED,
+ FLUSH_DONE,
+};
+
/**
* struct efx_tx_buffer - An Efx TX buffer
* @skb: The associated socket buffer.
@@ -189,7 +196,7 @@ struct efx_tx_queue {
struct efx_nic *nic;
struct efx_tx_buffer *buffer;
struct efx_special_buffer txd;
- bool flushed;
+ enum efx_flush_state flushed;
/* Members used mainly on the completion path */
unsigned int read_count ____cacheline_aligned_in_smp;
@@ -284,7 +291,7 @@ struct efx_rx_queue {
struct page *buf_page;
dma_addr_t buf_dma_addr;
char *buf_data;
- bool flushed;
+ enum efx_flush_state flushed;
};
/**
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 06/16] sfc: Clean up struct falcon_board and struct falcon_board_data
From: Ben Hutchings @ 2009-11-26 2:09 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Put all static information in struct falcon_board_type and replace it
with a pointer in struct falcon_board. Simplify probing aocordingly.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/efx.c | 2 +-
drivers/net/sfc/ethtool.c | 6 +-
drivers/net/sfc/falcon.c | 4 +-
drivers/net/sfc/falcon.h | 34 ++++++++----
drivers/net/sfc/falcon_boards.c | 115 ++++++++++++++++++---------------------
drivers/net/sfc/qt202x_phy.c | 2 +-
drivers/net/sfc/tenxpress.c | 2 +-
7 files changed, 85 insertions(+), 80 deletions(-)
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 9f3ef38..dc85efa 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1309,7 +1309,7 @@ static void efx_monitor(struct work_struct *data)
goto out_requeue;
if (!efx->port_enabled)
goto out_unlock;
- rc = falcon_board(efx)->monitor(efx);
+ rc = falcon_board(efx)->type->monitor(efx);
if (rc) {
EFX_ERR(efx, "Board sensor %s; shutting down PHY\n",
(rc == -ERANGE) ? "reported fault" : "failed");
diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c
index d8915b9..bb9abf2 100644
--- a/drivers/net/sfc/ethtool.c
+++ b/drivers/net/sfc/ethtool.c
@@ -174,14 +174,14 @@ static int efx_ethtool_phys_id(struct net_device *net_dev, u32 count)
struct efx_nic *efx = netdev_priv(net_dev);
do {
- falcon_board(efx)->set_id_led(efx, EFX_LED_ON);
+ falcon_board(efx)->type->set_id_led(efx, EFX_LED_ON);
schedule_timeout_interruptible(HZ / 2);
- falcon_board(efx)->set_id_led(efx, EFX_LED_OFF);
+ falcon_board(efx)->type->set_id_led(efx, EFX_LED_OFF);
schedule_timeout_interruptible(HZ / 2);
} while (!signal_pending(current) && --count != 0);
- falcon_board(efx)->set_id_led(efx, EFX_LED_DEFAULT);
+ falcon_board(efx)->type->set_id_led(efx, EFX_LED_DEFAULT);
return 0;
}
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 2c0be6c..2f1f1fc 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -2864,7 +2864,7 @@ int falcon_probe_nic(struct efx_nic *efx)
if (rc)
goto fail5;
- rc = falcon_board(efx)->init(efx);
+ rc = falcon_board(efx)->type->init(efx);
if (rc) {
EFX_ERR(efx, "failed to initialise board\n");
goto fail6;
@@ -3067,7 +3067,7 @@ void falcon_remove_nic(struct efx_nic *efx)
struct falcon_board *board = falcon_board(efx);
int rc;
- falcon_board(efx)->fini(efx);
+ board->type->fini(efx);
/* Remove I2C adapter and clear it in preparation for a retry */
rc = i2c_del_adapter(&board->i2c_adap);
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index ea6ac06..b331889 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -31,29 +31,41 @@ static inline int falcon_rev(struct efx_nic *efx)
}
/**
- * struct falcon_board - board information
- * @type: Board model type
- * @major: Major rev. ('A', 'B' ...)
- * @minor: Minor rev. (0, 1, ...)
+ * struct falcon_board_type - board operations and type information
+ * @id: Board type id, as found in NVRAM
+ * @ref_model: Model number of Solarflare reference design
+ * @gen_type: Generic board type description
* @init: Allocate resources and initialise peripheral hardware
* @init_phy: Do board-specific PHY initialisation
+ * @fini: Shut down hardware and free resources
* @set_id_led: Set state of identifying LED or revert to automatic function
* @monitor: Board-specific health check function
- * @fini: Shut down hardware and free resources
+ */
+struct falcon_board_type {
+ u8 id;
+ const char *ref_model;
+ const char *gen_type;
+ int (*init) (struct efx_nic *nic);
+ void (*init_phy) (struct efx_nic *efx);
+ void (*fini) (struct efx_nic *nic);
+ void (*set_id_led) (struct efx_nic *efx, enum efx_led_mode mode);
+ int (*monitor) (struct efx_nic *nic);
+};
+
+/**
+ * struct falcon_board - board information
+ * @type: Type of board
+ * @major: Major rev. ('A', 'B' ...)
+ * @minor: Minor rev. (0, 1, ...)
* @i2c_adap: I2C adapter for on-board peripherals
* @i2c_data: Data for bit-banging algorithm
* @hwmon_client: I2C client for hardware monitor
* @ioexp_client: I2C client for power/port control
*/
struct falcon_board {
- int type;
+ const struct falcon_board_type *type;
int major;
int minor;
- int (*init) (struct efx_nic *nic);
- void (*init_phy) (struct efx_nic *efx);
- void (*set_id_led) (struct efx_nic *efx, enum efx_led_mode mode);
- int (*monitor) (struct efx_nic *nic);
- void (*fini) (struct efx_nic *nic);
struct i2c_adapter i2c_adap;
struct i2c_algo_bit_data i2c_data;
struct i2c_client *hwmon_client, *ioexp_client;
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index f05c9d3..ac1258e 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -348,7 +348,7 @@ static ssize_t set_phy_flash_cfg(struct device *dev,
efx->phy_mode = new_mode;
if (new_mode & PHY_MODE_SPECIAL)
efx_stats_disable(efx);
- if (falcon_board(efx)->type == FALCON_BOARD_SFE4001)
+ if (falcon_board(efx)->type->id == FALCON_BOARD_SFE4001)
err = sfe4001_poweron(efx);
else
err = sfn4111t_reset(efx);
@@ -438,13 +438,6 @@ static int sfe4001_init(struct efx_nic *efx)
goto fail_hwmon;
}
- /* 10Xpress has fixed-function LED pins, so there is no board-specific
- * blink code. */
- board->set_id_led = tenxpress_set_id_led;
-
- board->monitor = sfe4001_check_hw;
- board->fini = sfe4001_fini;
-
if (efx->phy_mode & PHY_MODE_SPECIAL) {
/* PHY won't generate a 156.25 MHz clock and MAC stats fetch
* will fail. */
@@ -531,11 +524,6 @@ static int sfn4111t_init(struct efx_nic *efx)
if (!board->hwmon_client)
return -EIO;
- board->init_phy = sfn4111t_init_phy;
- board->set_id_led = tenxpress_set_id_led;
- board->monitor = sfn4111t_check_hw;
- board->fini = sfn4111t_fini;
-
rc = device_create_file(&efx->pci_dev->dev, &dev_attr_phy_flash_cfg);
if (rc)
goto fail_hwmon;
@@ -620,15 +608,7 @@ static int sfe4002_check_hw(struct efx_nic *efx)
static int sfe4002_init(struct efx_nic *efx)
{
- struct falcon_board *board = falcon_board(efx);
- int rc = efx_init_lm87(efx, &sfe4002_hwmon_info, sfe4002_lm87_regs);
- if (rc)
- return rc;
- board->monitor = sfe4002_check_hw;
- board->init_phy = sfe4002_init_phy;
- board->set_id_led = sfe4002_set_id_led;
- board->fini = efx_fini_lm87;
- return 0;
+ return efx_init_lm87(efx, &sfe4002_hwmon_info, sfe4002_lm87_regs);
}
/*****************************************************************************
@@ -692,67 +672,80 @@ static int sfn4112f_check_hw(struct efx_nic *efx)
static int sfn4112f_init(struct efx_nic *efx)
{
- struct falcon_board *board = falcon_board(efx);
-
- int rc = efx_init_lm87(efx, &sfn4112f_hwmon_info, sfn4112f_lm87_regs);
- if (rc)
- return rc;
- board->monitor = sfn4112f_check_hw;
- board->init_phy = sfn4112f_init_phy;
- board->set_id_led = sfn4112f_set_id_led;
- board->fini = efx_fini_lm87;
- return 0;
+ return efx_init_lm87(efx, &sfn4112f_hwmon_info, sfn4112f_lm87_regs);
}
-/* This will get expanded as board-specific details get moved out of the
- * PHY drivers. */
-struct falcon_board_data {
- u8 type;
- const char *ref_model;
- const char *gen_type;
- int (*init) (struct efx_nic *nic);
-};
-
-
-static struct falcon_board_data board_data[] = {
- { FALCON_BOARD_SFE4001, "SFE4001", "10GBASE-T adapter", sfe4001_init },
- { FALCON_BOARD_SFE4002, "SFE4002", "XFP adapter", sfe4002_init },
- { FALCON_BOARD_SFN4111T, "SFN4111T", "100/1000/10GBASE-T adapter",
- sfn4111t_init },
- { FALCON_BOARD_SFN4112F, "SFN4112F", "SFP+ adapter",
- sfn4112f_init },
+static const struct falcon_board_type board_types[] = {
+ {
+ .id = FALCON_BOARD_SFE4001,
+ .ref_model = "SFE4001",
+ .gen_type = "10GBASE-T adapter",
+ .init = sfe4001_init,
+ .init_phy = efx_port_dummy_op_void,
+ .fini = sfe4001_fini,
+ .set_id_led = tenxpress_set_id_led,
+ .monitor = sfe4001_check_hw,
+ },
+ {
+ .id = FALCON_BOARD_SFE4002,
+ .ref_model = "SFE4002",
+ .gen_type = "XFP adapter",
+ .init = sfe4002_init,
+ .init_phy = sfe4002_init_phy,
+ .fini = efx_fini_lm87,
+ .set_id_led = sfe4002_set_id_led,
+ .monitor = sfe4002_check_hw,
+ },
+ {
+ .id = FALCON_BOARD_SFN4111T,
+ .ref_model = "SFN4111T",
+ .gen_type = "100/1000/10GBASE-T adapter",
+ .init = sfn4111t_init,
+ .init_phy = sfn4111t_init_phy,
+ .fini = sfn4111t_fini,
+ .set_id_led = tenxpress_set_id_led,
+ .monitor = sfn4111t_check_hw,
+ },
+ {
+ .id = FALCON_BOARD_SFN4112F,
+ .ref_model = "SFN4112F",
+ .gen_type = "SFP+ adapter",
+ .init = sfn4112f_init,
+ .init_phy = sfn4112f_init_phy,
+ .fini = efx_fini_lm87,
+ .set_id_led = sfn4112f_set_id_led,
+ .monitor = sfn4112f_check_hw,
+ },
};
-static struct falcon_board falcon_dummy_board = {
+static const struct falcon_board_type falcon_dummy_board = {
.init = efx_port_dummy_op_int,
.init_phy = efx_port_dummy_op_void,
+ .fini = efx_port_dummy_op_void,
.set_id_led = efx_port_dummy_op_set_id_led,
.monitor = efx_port_dummy_op_int,
- .fini = efx_port_dummy_op_void,
};
void falcon_probe_board(struct efx_nic *efx, u16 revision_info)
{
struct falcon_board *board = falcon_board(efx);
- struct falcon_board_data *data = NULL;
+ u8 type_id = FALCON_BOARD_TYPE(revision_info);
int i;
- *board = falcon_dummy_board;
- board->type = FALCON_BOARD_TYPE(revision_info);
board->major = FALCON_BOARD_MAJOR(revision_info);
board->minor = FALCON_BOARD_MINOR(revision_info);
- for (i = 0; i < ARRAY_SIZE(board_data); i++)
- if (board_data[i].type == board->type)
- data = &board_data[i];
+ for (i = 0; i < ARRAY_SIZE(board_types); i++)
+ if (board_types[i].id == type_id)
+ board->type = &board_types[i];
- if (data) {
+ if (board->type) {
EFX_INFO(efx, "board is %s rev %c%d\n",
(efx->pci_dev->subsystem_vendor == EFX_VENDID_SFC)
- ? data->ref_model : data->gen_type,
+ ? board->type->ref_model : board->type->gen_type,
'A' + board->major, board->minor);
- board->init = data->init;
} else {
- EFX_ERR(efx, "unknown board type %d\n", board->type);
+ EFX_ERR(efx, "unknown board type %d\n", type_id);
+ board->type = &falcon_dummy_board;
}
}
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c
index 8208ac0..f9c354e 100644
--- a/drivers/net/sfc/qt202x_phy.c
+++ b/drivers/net/sfc/qt202x_phy.c
@@ -126,7 +126,7 @@ static int qt202x_reset_phy(struct efx_nic *efx)
if (rc < 0)
goto fail;
- falcon_board(efx)->init_phy(efx);
+ falcon_board(efx)->type->init_phy(efx);
return rc;
diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c
index b001f38..a95402d 100644
--- a/drivers/net/sfc/tenxpress.c
+++ b/drivers/net/sfc/tenxpress.c
@@ -303,7 +303,7 @@ static int tenxpress_phy_init(struct efx_nic *efx)
u16 old_adv, adv;
int rc = 0;
- falcon_board(efx)->init_phy(efx);
+ falcon_board(efx)->type->init_phy(efx);
phy_data = kzalloc(sizeof(*phy_data), GFP_KERNEL);
if (!phy_data)
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 05/16] sfc: Remove unused constant
From: Ben Hutchings @ 2009-11-26 2:09 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/falcon.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 140087f..2c0be6c 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -109,9 +109,6 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
/* Size and alignment of special buffers (4KB) */
#define FALCON_BUF_SIZE 4096
-/* Dummy SRAM size code */
-#define SRM_NB_BSZ_ONCHIP_ONLY (-1)
-
#define FALCON_IS_DUAL_FUNC(efx) \
(falcon_rev(efx) < FALCON_REV_B0)
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 04/16] sfc: Comment corrections
From: Ben Hutchings @ 2009-11-26 2:09 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/falcon.c | 5 +----
drivers/net/sfc/falcon.h | 2 +-
drivers/net/sfc/falcon_boards.c | 2 +-
3 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index f97ef3e..140087f 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -27,10 +27,7 @@
#include "phy.h"
#include "workarounds.h"
-/* Falcon hardware control.
- * Falcon is the internal codename for the SFC4000 controller that is
- * present in SFE400X evaluation boards
- */
+/* Hardware control for SFC4000 (aka Falcon). */
/**************************************************************************
*
diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h
index 0da5ea7..ea6ac06 100644
--- a/drivers/net/sfc/falcon.h
+++ b/drivers/net/sfc/falcon.h
@@ -61,7 +61,7 @@ struct falcon_board {
/**
* struct falcon_nic_data - Falcon NIC state
- * @pci_dev2: The secondary PCI device if present
+ * @pci_dev2: Secondary function of Falcon A
* @board: Board state and functions
*/
struct falcon_nic_data {
diff --git a/drivers/net/sfc/falcon_boards.c b/drivers/net/sfc/falcon_boards.c
index 333ccc1..f05c9d3 100644
--- a/drivers/net/sfc/falcon_boards.c
+++ b/drivers/net/sfc/falcon_boards.c
@@ -144,7 +144,7 @@ static inline int efx_check_lm87(struct efx_nic *efx, unsigned mask)
*/
/**************************************************************************
- * Support for I2C IO Expander device on SFE40001
+ * Support for I2C IO Expander device on SFE4001
*/
#define PCA9539 0x74
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 03/16] sfc: Strengthen EFX_ASSERT_RESET_SERIALISED
From: Ben Hutchings @ 2009-11-26 2:08 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/efx.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 4787faa..9f3ef38 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -186,7 +186,8 @@ static void efx_fini_channels(struct efx_nic *efx);
#define EFX_ASSERT_RESET_SERIALISED(efx) \
do { \
- if (efx->state == STATE_RUNNING) \
+ if ((efx->state == STATE_RUNNING) || \
+ (efx->state == STATE_DISABLED)) \
ASSERT_RTNL(); \
} while (0)
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 02/16] sfc: Treat all MAC registers as 128-bit
From: Ben Hutchings @ 2009-11-26 2:08 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
Although all the defined fields in these registers are within 32 bits,
they are architecturally defined as 128-bit like most other Falcon
registers. In particular, we must use efx_reado() to ensure proper
locking when reading MD_STAT_REG.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/falcon.c | 14 +++++++-------
drivers/net/sfc/falcon_xmac.c | 14 +++++++-------
2 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 7b19686..f97ef3e 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -2042,18 +2042,18 @@ int falcon_dma_stats(struct efx_nic *efx, unsigned int done_offset)
/* Wait for GMII access to complete */
static int falcon_gmii_wait(struct efx_nic *efx)
{
- efx_dword_t md_stat;
+ efx_oword_t md_stat;
int count;
/* wait upto 50ms - taken max from datasheet */
for (count = 0; count < 5000; count++) {
- efx_readd(efx, &md_stat, FR_AB_MD_STAT);
- if (EFX_DWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) {
- if (EFX_DWORD_FIELD(md_stat, FRF_AB_MD_LNFL) != 0 ||
- EFX_DWORD_FIELD(md_stat, FRF_AB_MD_BSERR) != 0) {
+ efx_reado(efx, &md_stat, FR_AB_MD_STAT);
+ if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) {
+ if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_LNFL) != 0 ||
+ EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSERR) != 0) {
EFX_ERR(efx, "error from GMII access "
- EFX_DWORD_FMT"\n",
- EFX_DWORD_VAL(md_stat));
+ EFX_OWORD_FMT"\n",
+ EFX_OWORD_VAL(md_stat));
return -EIO;
}
return 0;
diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c
index 69cb55f..cf24513 100644
--- a/drivers/net/sfc/falcon_xmac.c
+++ b/drivers/net/sfc/falcon_xmac.c
@@ -64,7 +64,7 @@ int falcon_reset_xaui(struct efx_nic *efx)
int count;
/* Start reset sequence */
- EFX_POPULATE_DWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1);
+ EFX_POPULATE_OWORD_1(reg, FRF_AB_XX_RST_XX_EN, 1);
efx_writeo(efx, ®, FR_AB_XX_PWR_RST);
/* Wait up to 10 ms for completion, then reinitialise */
@@ -146,14 +146,14 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
bool rx_fc = !!(efx->link_state.fc & EFX_FC_RX);
/* Configure MAC - cut-thru mode is hard wired on */
- EFX_POPULATE_DWORD_3(reg,
+ EFX_POPULATE_OWORD_3(reg,
FRF_AB_XM_RX_JUMBO_MODE, 1,
FRF_AB_XM_TX_STAT_EN, 1,
FRF_AB_XM_RX_STAT_EN, 1);
efx_writeo(efx, ®, FR_AB_XM_GLB_CFG);
/* Configure TX */
- EFX_POPULATE_DWORD_6(reg,
+ EFX_POPULATE_OWORD_6(reg,
FRF_AB_XM_TXEN, 1,
FRF_AB_XM_TX_PRMBL, 1,
FRF_AB_XM_AUTO_PAD, 1,
@@ -163,7 +163,7 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
efx_writeo(efx, ®, FR_AB_XM_TX_CFG);
/* Configure RX */
- EFX_POPULATE_DWORD_5(reg,
+ EFX_POPULATE_OWORD_5(reg,
FRF_AB_XM_RXEN, 1,
FRF_AB_XM_AUTO_DEPAD, 0,
FRF_AB_XM_ACPT_ALL_MCAST, 1,
@@ -173,14 +173,14 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx)
/* Set frame length */
max_frame_len = EFX_MAX_FRAME_LEN(efx->net_dev->mtu);
- EFX_POPULATE_DWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len);
+ EFX_POPULATE_OWORD_1(reg, FRF_AB_XM_MAX_RX_FRM_SIZE, max_frame_len);
efx_writeo(efx, ®, FR_AB_XM_RX_PARAM);
- EFX_POPULATE_DWORD_2(reg,
+ EFX_POPULATE_OWORD_2(reg,
FRF_AB_XM_MAX_TX_FRM_SIZE, max_frame_len,
FRF_AB_XM_TX_JUMBO_MODE, 1);
efx_writeo(efx, ®, FR_AB_XM_TX_PARAM);
- EFX_POPULATE_DWORD_2(reg,
+ EFX_POPULATE_OWORD_2(reg,
FRF_AB_XM_PAUSE_TIME, 0xfffe, /* MAX PAUSE TIME */
FRF_AB_XM_DIS_FCNTL, !rx_fc);
efx_writeo(efx, ®, FR_AB_XM_FC);
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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 01/16] sfc: Fix descriptor cache sizes
From: Ben Hutchings @ 2009-11-26 2:08 UTC (permalink / raw)
To: David Miller; +Cc: netdev, linux-net-drivers
These were accidentally undersized by a factor of 2, which limited
performance.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
---
drivers/net/sfc/falcon.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c
index 41a321b..7b19686 100644
--- a/drivers/net/sfc/falcon.c
+++ b/drivers/net/sfc/falcon.c
@@ -49,11 +49,11 @@ static int disable_dma_stats;
* goes idle.
*/
#define TX_DC_ENTRIES 16
-#define TX_DC_ENTRIES_ORDER 0
+#define TX_DC_ENTRIES_ORDER 1
#define TX_DC_BASE 0x130000
#define RX_DC_ENTRIES 64
-#define RX_DC_ENTRIES_ORDER 2
+#define RX_DC_ENTRIES_ORDER 3
#define RX_DC_BASE 0x100000
static const unsigned int
@@ -2974,14 +2974,14 @@ int falcon_init_nic(struct efx_nic *efx)
efx_writeo(efx, &temp, FR_AZ_SRM_RX_DC_CFG);
/* Set TX descriptor cache size. */
- BUILD_BUG_ON(TX_DC_ENTRIES != (16 << TX_DC_ENTRIES_ORDER));
+ BUILD_BUG_ON(TX_DC_ENTRIES != (8 << TX_DC_ENTRIES_ORDER));
EFX_POPULATE_OWORD_1(temp, FRF_AZ_TX_DC_SIZE, TX_DC_ENTRIES_ORDER);
efx_writeo(efx, &temp, FR_AZ_TX_DC_CFG);
/* Set RX descriptor cache size. Set low watermark to size-8, as
* this allows most efficient prefetching.
*/
- BUILD_BUG_ON(RX_DC_ENTRIES != (16 << RX_DC_ENTRIES_ORDER));
+ BUILD_BUG_ON(RX_DC_ENTRIES != (8 << RX_DC_ENTRIES_ORDER));
EFX_POPULATE_OWORD_1(temp, FRF_AZ_RX_DC_SIZE, RX_DC_ENTRIES_ORDER);
efx_writeo(efx, &temp, FR_AZ_RX_DC_CFG);
EFX_POPULATE_OWORD_1(temp, FRF_AZ_RX_DC_PF_LWM, RX_DC_ENTRIES - 8);
--
Ben Hutchings, Senior Software Engineer, Solarflare Communications
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
* [rfc 3/3 v3] [E1000-devel] [rfc 4/4] igb: expose 82576 bandiwidth allocation
From: Simon Horman @ 2009-11-26 0:05 UTC (permalink / raw)
To: e1000-devel, netdev; +Cc: Arnd Bergmann, Alexander Duyck, Jeff Kirsher
In-Reply-To: <20091126000538.716725330@vergenet.net>
[-- Attachment #1: igb-expose-82576-bandwidth-allocation-2.patch --]
[-- Type: text/plain, Size: 12316 bytes --]
The 82576 has support for bandwidth allocation to VFs.
Contrary to the documentation in the 82576 datasheet v2.41 this
appears to work as follows:
* The ratio supplied is always proportional to 1Gbit/s,
regardless of if the link speed.
* The ratio supplied is an upper-bound on bandwidth available
to the VF, not a minimun guarantee
This patch exposes bandwidth control to userspace through a simple
per-device (PF) sysfs file, bandwidth_allocation.
* The file contains a whitespace delimited list of values, one per VF.
* The first value corresponds to the first VF and so on.
* Valid values are integers from 0 to 1000
* A value of 0 indicates that bandwidth_allocation is disabled.
* Other values indicate the allocated bandwidth, in 1/1000ths of a gigabit/s
e.g. The following for a PF with 4 VFs allocates ~20Mbits/ to VF 1,
~100Mbit/s to VF 2, and leave the other 2 VFs with no allocation.
echo "20 100 0 0" > /sys/class/net/eth3/device/bandwidth_allocation
This interface is intended to allow testing of the hardware feature.
There are ongoing discussions about how to expose this feature
to user-space in a more generic way.
Cc: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
Thu, 05 Nov 2009 11:58:51 +1100
* Initial post
Wed, 25 Nov 2009 16:58:23 +1100
* Refresh for changes to proceeding patches in series
* Up-port to latest net-next
Index: net-next-2.6/drivers/net/igb/igb_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/igb/igb_main.c 2009-11-26 10:33:01.000000000 +1100
+++ net-next-2.6/drivers/net/igb/igb_main.c 2009-11-26 10:33:01.000000000 +1100
@@ -47,6 +47,9 @@
#ifdef CONFIG_IGB_DCA
#include <linux/dca.h>
#endif
+#ifdef CONFIG_PCI_IOV
+#include <linux/ctype.h>
+#endif
#include "igb.h"
#define DRV_VERSION "2.1.0-k2"
@@ -157,6 +160,15 @@ static unsigned int max_vfs = 0;
module_param(max_vfs, uint, 0);
MODULE_PARM_DESC(max_vfs, "Maximum number of virtual functions to allocate "
"per physical function");
+
+static ssize_t igb_set_bandwidth_allocation(struct device *,
+ struct device_attribute *,
+ const char *, size_t);
+static ssize_t igb_show_bandwidth_allocation(struct device *,
+ struct device_attribute *,
+ char *);
+DEVICE_ATTR(bandwidth_allocation, S_IRUGO | S_IWUSR,
+ igb_show_bandwidth_allocation, igb_set_bandwidth_allocation);
#endif /* CONFIG_PCI_IOV */
static pci_ers_result_t igb_io_error_detected(struct pci_dev *,
@@ -1760,6 +1772,19 @@ static void __devinit igb_init_vf(struct
if (pci_enable_sriov(pdev, adapter->vfs_allocated_count))
goto err_free;
+ if (device_create_file(&pdev->dev, &dev_attr_bandwidth_allocation))
+ goto err_sriov;
+
+ adapter->bandwidth_allocation = kcalloc(adapter->vfs_allocated_count,
+ sizeof(unsigned int),
+ GFP_KERNEL);
+ if (!adapter->bandwidth_allocation)
+ goto err_file;
+ memset(adapter->bandwidth_allocation,
+ adapter->vfs_allocated_count * sizeof(unsigned int), 0);
+
+ spin_lock_init(&adapter->bandwidth_allocation_lock);
+
dev_info(&pdev->dev, "%d vfs allocated\n",
adapter->vfs_allocated_count);
for (i = 0; i < adapter->vfs_allocated_count; i++) {
@@ -1768,6 +1793,10 @@ static void __devinit igb_init_vf(struct
}
return;
+err_file:
+ device_remove_file(&pdev->dev, &dev_attr_bandwidth_allocation);
+err_sriov:
+ pci_disable_sriov(pdev);
err_free:
kfree(adapter->vf_data);
err_zero:
@@ -1892,6 +1921,7 @@ static void igb_init_hw_timer(struct igb
static void igb_cleanup_vf(struct igb_adapter * adapter)
{
#ifdef CONFIG_PCI_IOV
+ struct pci_dev *pdev = adapter->pdev;
struct e1000_hw *hw = &adapter->hw;
if (!adapter->vf_data)
@@ -1908,6 +1938,9 @@ static void igb_cleanup_vf(struct igb_ad
wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
msleep(100);
dev_info(&adapter->pdev->dev, "IOV Disabled\n");
+
+ device_remove_file(&pdev->dev, &dev_attr_bandwidth_allocation);
+ kfree(adapter->bandwidth_allocation);
#endif
}
@@ -2216,6 +2249,123 @@ void igb_configure_tx_ring(struct igb_ad
wr32(E1000_TXDCTL(reg_idx), txdctl);
}
+#ifdef CONFIG_PCI_IOV
+static void igb_disable_bandwidth_allocation_vf(struct e1000_hw *hw, int vf)
+{
+ wr32(E1000_VMBASEL, vf);
+ wr32(E1000_VMBAC, 0);
+}
+
+static void igb_disable_bandwidth_allocation(struct igb_adapter *adapter)
+{
+ struct e1000_hw *hw = &adapter->hw;
+ int i;
+
+ for (i = 0; i < adapter->vfs_allocated_count; i++)
+ igb_disable_bandwidth_allocation_vf(hw, i);
+}
+
+static void igb_enable_bandwidth_allocation_vf(struct e1000_hw *hw, int vf,
+ unsigned int allocation)
+{
+ u32 rq;
+
+ /* Allocation is expressed as 1000ths of link speed [+]
+ *
+ * rq is calcualted as 1 / (allocation / 1000) = 1000 / allocation
+ *
+ * E1000_VMBAC_RF_INT_SHIFT and E1000_VMBAC_RF_MASK are used
+ * to marshal the result into the desired format: 23 bits of
+ * which 14 are to the right of the decimal point.
+ *
+ * [+] According to the the 82576 v2.41 datasheet rq should
+ * be a ratio of the link speed, however, empirically
+ * it appears to always be a ration of to 1Gbit/s,
+ * even when the link is 100Mbit/s.
+ */
+ rq = ((1000 << E1000_VMBAC_RF_INT_SHIFT) / allocation) &
+ E1000_VMBAC_RF_MASK;
+
+ wr32(E1000_VMBASEL, vf);
+ wr32(E1000_VMBAC, rq|E1000_VMBAC_RC_ENA);
+}
+
+static void igb_enable_bandwidth_allocation(struct igb_adapter *adapter)
+{
+ u32 i, reg;
+ struct e1000_hw *hw = &adapter->hw;
+
+ /* Only enable bandwidth_allocation if it has been set
+ * and the link speed is 100Mbit/s or 1Gbit/s */
+ if (!adapter->bandwidth_allocation ||
+ (adapter->link_speed != SPEED_100 &&
+ adapter->link_speed != SPEED_1000)) {
+ igb_disable_bandwidth_allocation(adapter);
+ return;
+ }
+
+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
+ wr32(E1000_VMBASEL, i);
+ if (adapter->bandwidth_allocation[i])
+ igb_enable_bandwidth_allocation_vf(hw, i,
+ adapter->bandwidth_allocation[i]);
+ else
+ igb_disable_bandwidth_allocation_vf(hw, i);
+
+ /* XXX:
+ *
+ * The 82576 datasheet, section 4.5.11.1.5.1 "Configuring Tx
+ * Bandwidth to VMs" states that the desired setting is:
+ * VMBAMMW.MMW_SIZE = 16 * MSS
+ *
+ * But isn't MSS a property of skbs that are using tso
+ * rather than adapters?
+ *
+ * If so, should we use the maximum value here? */
+ /* XXX: Should this go inside or outside the for loop ? */
+ reg = 64 * 16;
+ wr32(E1000_VMBAMMW, reg);
+ }
+}
+#endif
+
+static void igb_check_bandwidth_allocation(struct igb_adapter *adapter)
+{
+#ifdef CONFIG_PCI_IOV
+ u32 vmbacs;
+ struct e1000_hw *hw = &adapter->hw;
+
+ if (!adapter->vf_data)
+ return;
+
+ /* The 82576 datasheet, section 4.5.11.1.5.2 "Link Speed Change
+ * Procedure" describes the sequence below. However the
+ * SPEED_CHG never seems to be set.
+ */
+ vmbacs = rd32(E1000_VMBACS);
+ if (vmbacs & E1000_VMBACS_SPEED_CHG) {
+ /* XXX: Never seem to get here */
+ int err = 0;
+
+ if (vmbacs & E1000_VMBACS_VMBA_SET) {
+ igb_disable_bandwidth_allocation(adapter);
+ err = 1;
+ }
+
+ vmbacs &= ~E1000_VMBACS_SPEED_CHG;
+ wr32(E1000_VMBACS, vmbacs);
+
+ if (err)
+ return;
+ }
+
+ spin_lock(&adapter->bandwidth_allocation_lock);
+ igb_enable_bandwidth_allocation(adapter);
+ spin_unlock(&adapter->bandwidth_allocation_lock);
+#endif
+ return;
+}
+
/**
* igb_configure_tx - Configure transmit Unit after Reset
* @adapter: board private structure
@@ -3100,6 +3250,8 @@ static void igb_watchdog_task(struct wor
break;
}
+ igb_check_bandwidth_allocation(adapter);
+
netif_carrier_on(netdev);
igb_ping_all_vfs(adapter);
@@ -5999,4 +6151,101 @@ static void igb_vmm_control(struct igb_a
}
}
+#ifdef CONFIG_PCI_IOV
+static ssize_t igb_show_bandwidth_allocation(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct net_device *netdev = dev_get_drvdata(dev);
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ int i;
+
+ if (!adapter->vf_data)
+ return -ENOENT;
+
+ *buf = '\0';
+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
+ if (i > 0)
+ strcat(buf, " ");
+ sprintf(buf + strlen(buf), "%i",
+ adapter->bandwidth_allocation[i]);
+ }
+ strcat(buf, "\n");
+
+ return strlen(buf);
+}
+
+static unsigned long igb_strtoul(const char *cp, char **endp, unsigned int base)
+{
+ const char *orig = cp;
+ unsigned long x;
+
+ while (isspace(*cp))
+ cp++;
+
+ x = simple_strtoul(cp, endp, base);
+ if (cp == *endp)
+ *endp = (char *)orig;
+
+ return x;
+}
+
+static ssize_t igb_set_bandwidth_allocation(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct net_device *netdev = dev_get_drvdata(dev);
+ struct igb_adapter *adapter = netdev_priv(netdev);
+ int i;
+ size_t len;
+ ssize_t status = -ENOENT;
+ unsigned int *new, total;
+ unsigned long x;
+ const char *p;
+ char *next_p;
+
+ if (!adapter->vf_data)
+ return -ENOENT;
+
+ len = adapter->vfs_allocated_count * sizeof(unsigned int);
+
+ new = kmalloc(len, GFP_KERNEL);
+ if (!new)
+ return -ENOMEM;
+
+ p = buf;
+ total = 0;
+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
+ x = igb_strtoul(p, &next_p, 10);
+ if (p == next_p) {
+ dev_err(dev, "not enough values\n");
+ goto err;
+ }
+ if (x > 1000) {
+ dev_err(dev, "value is too large\n");
+ goto err;
+ }
+ new[i] = x;
+ total += x;
+ p = next_p;
+ }
+
+ /* Check for trailing rubbish */
+ igb_strtoul(p, &next_p, 10);
+ if (p != next_p) {
+ dev_err(dev, "trailing rubbish\n");
+ goto err;
+ }
+
+ spin_lock(&adapter->bandwidth_allocation_lock);
+ memcpy(adapter->bandwidth_allocation, new, len);
+ igb_enable_bandwidth_allocation(adapter);
+ spin_unlock(&adapter->bandwidth_allocation_lock);
+
+ status = count;
+err:
+ kfree(new);
+ return status;
+}
+#endif /* CONFIG_PCI_IOV */
/* igb_main.c */
Index: net-next-2.6/drivers/net/igb/e1000_regs.h
===================================================================
--- net-next-2.6.orig/drivers/net/igb/e1000_regs.h 2009-11-26 10:32:02.000000000 +1100
+++ net-next-2.6/drivers/net/igb/e1000_regs.h 2009-11-26 10:33:01.000000000 +1100
@@ -311,6 +311,16 @@
#define E1000_VLVF(_n) (0x05D00 + (4 * (_n))) /* VLAN Virtual Machine
* Filter - RW */
+/* Tx Bandwidth Allocation to VM Registers */
+#define E1000_VMBACS 0x03600 /* VM Bandwidth Allocation
+ * Control & Status - RW */
+#define E1000_VMBAMMW 0x03670 /* VM Bandwidth Allocation
+ * Max Memory Window - RW */
+#define E1000_VMBASEL 0x03604 /* VM Bandwidth Allocation
+ * Select - RW */
+#define E1000_VMBAC 0x03608 /* VM Bandwidth Allocation
+ * Config - RW */
+
#define wr32(reg, value) (writel(value, hw->hw_addr + reg))
#define rd32(reg) (readl(hw->hw_addr + reg))
#define wrfl() ((void)rd32(E1000_STATUS))
Index: net-next-2.6/drivers/net/igb/e1000_defines.h
===================================================================
--- net-next-2.6.orig/drivers/net/igb/e1000_defines.h 2009-11-26 10:32:02.000000000 +1100
+++ net-next-2.6/drivers/net/igb/e1000_defines.h 2009-11-26 10:33:01.000000000 +1100
@@ -724,4 +724,13 @@
#define E1000_PCIEMISC_LX_DECISION 0x00000080 /* Lx power decision based
on DMA coal */
+/* VM Bandwidth Allocation Control & Status */
+#define E1000_VMBACS_VMBA_SET 0x00001000
+#define E1000_VMBACS_SPEED_CHG 0x80000000
+
+/* VM Bandwidth Allocation Config */
+#define E1000_VMBAC_RF_INT_SHIFT 14
+#define E1000_VMBAC_RF_MASK ((1<<23)-1) /* RF_DEC and RF_INT */
+#define E1000_VMBAC_RC_ENA 0x80000000
+
#endif
Index: net-next-2.6/drivers/net/igb/igb.h
===================================================================
--- net-next-2.6.orig/drivers/net/igb/igb.h 2009-11-26 10:32:02.000000000 +1100
+++ net-next-2.6/drivers/net/igb/igb.h 2009-11-26 10:33:01.000000000 +1100
@@ -312,6 +312,10 @@ struct igb_adapter {
unsigned int vfs_allocated_count;
struct vf_data_storage *vf_data;
u32 rss_queues;
+#ifdef CONFIG_PCI_IOV
+ unsigned int *bandwidth_allocation;
+ spinlock_t bandwidth_allocation_lock;
+#endif
};
#define IGB_FLAG_HAS_MSI (1 << 0)
^ permalink raw reply
* [rfc 2/3 v3] [E1000-devel] [rfc 3/4] igb: Common error path in igb_init_vfs()
From: Simon Horman @ 2009-11-26 0:05 UTC (permalink / raw)
To: e1000-devel, netdev; +Cc: Arnd Bergmann, Alexander Duyck, Jeff Kirsher
In-Reply-To: <20091126000538.716725330@vergenet.net>
[-- Attachment #1: igb-common-error-path-in-igb_init_vfs.2.patch --]
[-- Type: text/plain, Size: 3297 bytes --]
Drop out into an error path on error.
This is a bit superfluous as things stand, though arguably
it already makes the code cleaner. But it should help things a lot
if igb_init_vfs() has a several things to unwind on error.
This patch eliminates resetting adapter->vfs_allocated_count to 0
in the case where CONFIG_PCI_IOV is not set, because in that
case adapter->vfs_allocated_count can never be non-zero.
Cc: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
Thu, 05 Nov 2009 11:58:50 +1100
* Initial post
Wed, 25 Nov 2009 16:44:15 +1100
* Merged with " Initialise adapter->vfs_allocated_count in igb_init_vf()",
however the initialisation of adapter->vfs_allocated_count is no
longer moved into igb_init_vf() as doing so results in a panic.
Thu, 26 Nov 2009 10:29:02 +1100
As per suggestions from Alexander Duyck
* Don't try and allocate vf_data if there are no vfs
* Zero out vfs_allocated_count and vf_data in the
non CONFIG_PCI_IOV case, just to be sure.
Index: net-next-2.6/drivers/net/igb/igb_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/igb/igb_main.c 2009-11-26 10:21:58.000000000 +1100
+++ net-next-2.6/drivers/net/igb/igb_main.c 2009-11-26 10:23:50.000000000 +1100
@@ -1753,39 +1753,41 @@ static void __devinit igb_init_vf(struct
{
#ifdef CONFIG_PCI_IOV
struct pci_dev *pdev = adapter->pdev;
+ unsigned char mac_addr[ETH_ALEN];
+ int i;
+
+ if (!adapter->vfs_allocated_count)
+ goto err_zero;
if (adapter->vfs_allocated_count > 7)
adapter->vfs_allocated_count = 7;
- if (adapter->vfs_allocated_count) {
- adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
- sizeof(struct vf_data_storage),
- GFP_KERNEL);
- /* if allocation failed then we do not support SR-IOV */
- if (!adapter->vf_data) {
- adapter->vfs_allocated_count = 0;
- dev_err(&pdev->dev, "Unable to allocate memory for VF "
- "Data Storage\n");
- }
+ adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
+ sizeof(struct vf_data_storage), GFP_KERNEL);
+ /* if allocation failed then we do not support SR-IOV */
+ if (!adapter->vf_data) {
+ dev_err(&pdev->dev, "Unable to allocate memory for VF "
+ "Data Storage\n");
+ goto err_zero;
}
- if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) {
- kfree(adapter->vf_data);
- adapter->vf_data = NULL;
-#endif /* CONFIG_PCI_IOV */
- adapter->vfs_allocated_count = 0;
-#ifdef CONFIG_PCI_IOV
- } else {
- unsigned char mac_addr[ETH_ALEN];
- int i;
- dev_info(&pdev->dev, "%d vfs allocated\n",
- adapter->vfs_allocated_count);
- for (i = 0; i < adapter->vfs_allocated_count; i++) {
- random_ether_addr(mac_addr);
- igb_set_vf_mac(adapter, i, mac_addr);
- }
+ if (pci_enable_sriov(pdev, adapter->vfs_allocated_count))
+ goto err_free;
+
+ dev_info(&pdev->dev, "%d vfs allocated\n",
+ adapter->vfs_allocated_count);
+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
+ random_ether_addr(mac_addr);
+ igb_set_vf_mac(adapter, i, mac_addr);
}
+
+ return;
+err_free:
+ kfree(adapter->vf_data);
+err_zero:
#endif /* CONFIG_PCI_IOV */
+ adapter->vf_data = NULL;
+ adapter->vfs_allocated_count = 0;
}
^ permalink raw reply
* [rfc 1/3 v3] [E1000-devel] [rfc 1/4] igb: Add igb_cleanup_vf()
From: Simon Horman @ 2009-11-26 0:05 UTC (permalink / raw)
To: e1000-devel, netdev; +Cc: Arnd Bergmann, Alexander Duyck, Jeff Kirsher
In-Reply-To: <20091126000538.716725330@vergenet.net>
[-- Attachment #1: igb-add-igb_cleanup-vf.patch --]
[-- Type: text/plain, Size: 4635 bytes --]
Move virtual function cleanup code into igb_cleanup_vf() and for the sake
of symmetry rename igb_probe_vfs() as igb_init_vf().
Although these functions aren't entirely symmetrical it should aid
maintenance by making the relationship between initialisation and cleanup
more obvious.
Cc: Alexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: Simon Horman <horms@verge.net.au>
---
Thu, 05 Nov 2009 11:58:48 +1100
* Initial post
Wed, 25 Nov 2009 15:43:45 +1100
* Actually remove adapter->vfs_allocated_count = 0 from outside of
igb_cleanup_vf()
* Up-port to current net-next
Thu, 26 Nov 2009 10:29:02 +1100
As per suggestion from Alexander Duyck
* Use igb_cleanup_vf() in igb_remove()
Index: net-next-2.6/drivers/net/igb/igb_main.c
===================================================================
--- net-next-2.6.orig/drivers/net/igb/igb_main.c 2009-11-26 10:31:13.000000000 +1100
+++ net-next-2.6/drivers/net/igb/igb_main.c 2009-11-26 10:32:02.000000000 +1100
@@ -92,6 +92,7 @@ void igb_update_stats(struct igb_adapter
static int igb_probe(struct pci_dev *, const struct pci_device_id *);
static void __devexit igb_remove(struct pci_dev *pdev);
static int igb_sw_init(struct igb_adapter *);
+static void igb_cleanup_vf(struct igb_adapter * adapter);
static int igb_open(struct net_device *);
static int igb_close(struct net_device *);
static void igb_configure_tx(struct igb_adapter *);
@@ -701,22 +702,7 @@ static void igb_set_interrupt_capability
/* If we can't do MSI-X, try MSI */
msi_only:
-#ifdef CONFIG_PCI_IOV
- /* disable SR-IOV for non MSI-X configurations */
- if (adapter->vf_data) {
- struct e1000_hw *hw = &adapter->hw;
- /* disable iov and allow time for transactions to clear */
- pci_disable_sriov(adapter->pdev);
- msleep(500);
-
- kfree(adapter->vf_data);
- adapter->vf_data = NULL;
- wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
- msleep(100);
- dev_info(&adapter->pdev->dev, "IOV Disabled\n");
- }
-#endif
- adapter->vfs_allocated_count = 0;
+ igb_cleanup_vf(adapter);
adapter->rss_queues = 1;
adapter->flags |= IGB_FLAG_QUEUE_PAIRS;
adapter->num_rx_queues = 1;
@@ -1725,21 +1711,7 @@ static void __devexit igb_remove(struct
igb_reset_phy(hw);
igb_clear_interrupt_scheme(adapter);
-
-#ifdef CONFIG_PCI_IOV
- /* reclaim resources allocated to VFs */
- if (adapter->vf_data) {
- /* disable iov and allow time for transactions to clear */
- pci_disable_sriov(pdev);
- msleep(500);
-
- kfree(adapter->vf_data);
- adapter->vf_data = NULL;
- wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
- msleep(100);
- dev_info(&pdev->dev, "IOV Disabled\n");
- }
-#endif
+ igb_cleanup_vf(adapter);
iounmap(hw->hw_addr);
if (hw->flash_address)
@@ -1755,7 +1727,7 @@ static void __devexit igb_remove(struct
}
/**
- * igb_probe_vfs - Initialize vf data storage and add VFs to pci config space
+ * igb_init_vf - Initialize vf data storage and add VFs to pci config space
* @adapter: board private structure to initialize
*
* This function initializes the vf specific data storage and then attempts to
@@ -1763,7 +1735,7 @@ static void __devexit igb_remove(struct
* mor expensive time wise to disable SR-IOV than it is to allocate and free
* the memory for the VFs.
**/
-static void __devinit igb_probe_vfs(struct igb_adapter * adapter)
+static void __devinit igb_init_vf(struct igb_adapter * adapter)
{
#ifdef CONFIG_PCI_IOV
struct pci_dev *pdev = adapter->pdev;
@@ -1909,6 +1881,35 @@ static void igb_init_hw_timer(struct igb
}
/**
+ * igb_cleanup_vf - Clean up vf data and remove vfs from pci config space
+ * @adapter: board private structure to initialize
+ *
+ * This function cleans-up the vf specific data storage and then attempts to
+ * deallocate the VFs.
+ **/
+static void igb_cleanup_vf(struct igb_adapter * adapter)
+{
+#ifdef CONFIG_PCI_IOV
+ struct e1000_hw *hw = &adapter->hw;
+
+ if (!adapter->vf_data)
+ return;
+
+ /* disable iov and allow time for transactions to clear */
+ pci_disable_sriov(adapter->pdev);
+ msleep(500);
+
+ kfree(adapter->vf_data);
+ adapter->vf_data = NULL;
+ adapter->vfs_allocated_count = 0;
+
+ wr32(E1000_IOVCTL, E1000_IOVCTL_REUSE_VFQ);
+ msleep(100);
+ dev_info(&adapter->pdev->dev, "IOV Disabled\n");
+#endif
+}
+
+/**
* igb_sw_init - Initialize general software structures (struct igb_adapter)
* @adapter: board private structure to initialize
*
@@ -1955,7 +1956,7 @@ static int __devinit igb_sw_init(struct
}
igb_init_hw_timer(adapter);
- igb_probe_vfs(adapter);
+ igb_init_vf(adapter);
/* Explicitly disable IRQ since the NIC can be in any state. */
igb_irq_disable(adapter);
^ permalink raw reply
* [rfc 0/3 v3] igb: bandwidth allocation
From: Simon Horman @ 2009-11-26 0:05 UTC (permalink / raw)
To: e1000-devel, netdev; +Cc: Arnd Bergmann, Jeff Kirsher
this series of patches exposes the bandwidth allocation hardware support of
the Intel 82576. It does so through a rather hackish sysfs entry. That
interface is just intended for testing so that the exposed hardware feature
can be exercised. I would like to find a generic way to expose this feature
to user-space.
v2
* Remove the patch "Initialise adapter->vfs_allocated_count in
igb_init_vf()" as it causes a panic.
v3
* Incorporate several suggestions from Alexander Duyck
as noted in the per-patch changelogs
------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day
trial. Simplify your report design, integration and deployment - and focus on
what you do best, core application coding. Discover what's new with
Crystal Reports now. http://p.sf.net/sfu/bobj-july
^ permalink raw reply
* Re: [PATCH] r8169: move PHY regs tables to .rodata
From: David Miller @ 2009-11-25 23:55 UTC (permalink / raw)
To: adobriyan; +Cc: netdev
In-Reply-To: <20091125213933.GA3455@x200.malnet.ru>
From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Thu, 26 Nov 2009 00:39:34 +0300
> As side effect, consume less stack.
>
> -rtl8169_get_mac_version [vmlinux]: 432
> -rtl8169_init_one [vmlinux]: 376
> +rtl8169_init_one [vmlinux]: 136
>
> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
There are a lot of differences in the tables in net-next-2.6's copy
of this driver, so I had to munge this a lot and do some things by
hand to apply it properly.
So, applied... but please always submit networking changes against the
proper tree, thanks.
^ permalink raw reply
* Re: [PATCH 0/3] xfrm: Custom truncation lengths for authentication algorithms
From: David Miller @ 2009-11-25 23:48 UTC (permalink / raw)
To: martin; +Cc: herbert, linux-crypto, netdev
In-Reply-To: <cover.1259142145.git.martin@strongswan.org>
From: Martin Willi <martin@strongswan.org>
Date: Wed, 25 Nov 2009 11:29:50 +0100
> The following patchset adds support for defining truncation lengths
> for authentication algorithms in userspace. The main purpose for this
> is to support SHA256 in IPsec using the standardized 128 bit
> instead of the currently used 96 bit truncation.
>
> Martin Willi (3):
> xfrm: Define new XFRM netlink auth attribute with specified
> truncation bits
> xfrm: Store aalg in xfrm_state with a user specified truncation
> length
> xfrm: Use the user specified truncation length in ESP and AH
All applied to net-next-2.6, thanks!
^ permalink raw reply
* Re: [PATCH] xfrm: Add SHA384 and SHA512 HMAC authentication algorithms to XFRM
From: David Miller @ 2009-11-25 23:49 UTC (permalink / raw)
To: herbert; +Cc: martin, linux-crypto, netdev
In-Reply-To: <20091125121140.GB28385@gondor.apana.org.au>
From: Herbert Xu <herbert@gondor.apana.org.au>
Date: Wed, 25 Nov 2009 20:11:40 +0800
> On Wed, Nov 25, 2009 at 11:58:39AM +0100, Martin Willi wrote:
>> These algorithms use a truncation of 192/256 bits, as specified
>> in RFC4868.
>>
>> Signed-off-by: Martin Willi <martin@strongswan.org>
>
> Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Applied to net-next-2.6
^ permalink raw reply
* Re: [Bugme-new] [Bug 14688] New: alignment of rx_skb in r8169 driver
From: David Miller @ 2009-11-25 23:45 UTC (permalink / raw)
To: akpm; +Cc: meyer, bugzilla-daemon, bugme-daemon, romieu, netdev
In-Reply-To: <20091125135507.2160a534.akpm@linux-foundation.org>
From: Andrew Morton <akpm@linux-foundation.org>
Date: Wed, 25 Nov 2009 13:55:07 -0800
>> (align - 1) & (unsigned long)skb->data
>>
>> which is wrong. I would suggest the following correction:
>>
>> pad = align ? align - ((align - 1) & (unsigned long)skb->data) : NET_IP_ALIGN;
>> if (pad == align) pad = 0; // optional
>> skb_reserve(skb, pad);
>>
>> A patch for r8169.c is provided as attachment.
>>
>
> Thanks, but..
>
> - please always submit patches via email, not via bugzilla.
> Documentation/SubmittingPatches goes into some detail.
>
> - prepare patches as a unified diff, in `patch -p1' form. It should
> look like:
...
> - Please cc at least the following on the patch:
>
> Francois Romieu <romieu@fr.zoreil.com>
> "David S. Miller" <davem@davemloft.net>
> netdev@vger.kernel.org
>
> - Don't forget the changelog and a Singed-off-by:!
> --
> 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
Also a better, more canonical, expression to use to fix this would
be:
align - ((align - 1) & (unsigned long)skb->data)
or similar.
^ permalink raw reply
* Re: [PATCH] net: convert /proc/net/rt_acct to seq_file
From: David Miller @ 2009-11-25 23:40 UTC (permalink / raw)
To: adobriyan; +Cc: netdev
In-Reply-To: <20091125074547.GA3467@x200.malnet.ru>
From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Wed, 25 Nov 2009 10:45:47 +0300
> Rewrite statistics accumulation to be in terms of structure fields,
> not raw u32 additions. Keep them in same order, though.
>
> This is the last user of create_proc_read_entry() in net/,
> please NAK all new ones as well as all new ->write_proc, ->read_proc and
> create_proc_entry() users. Cc me if there are problems. :-)
>
> Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Applied, thanks Alexey.
^ permalink raw reply
* Re: [PATCH v3 5/7] via-velocity: Re-enable transmit scatter-gather support
From: David Miller @ 2009-11-25 23:37 UTC (permalink / raw)
To: simon.kagstrom; +Cc: netdev, davej, shemminger, romieu
In-Reply-To: <20091125092213.423d0dd7@marrow.netinsight.se>
From: Simon Kagstrom <simon.kagstrom@netinsight.net>
Date: Wed, 25 Nov 2009 09:22:13 +0100
> The velocity hardware can handle up to 7 memory segments. This can be
> turned on and off via ethtool. The support was removed in commit
>
> 83c98a8cd04dd0f848574370594886ba3bf56750
>
> but is re-enabled and cleaned up here. It's off by default.
>
> Signed-off-by: Simon Kagstrom <simon.kagstrom@netinsight.net>
> ---
> ChangeLog:
>
> * (David Miller) return NETDEV_TX_OK from the velocity_xmit
> function. I'm still a bit unsure on what to actually return in
> these cases (they are error cases), but other drivers seem to
> return NETDEV_TX_OK, so that's what I went with.
This still isn't right, sorry.
If you return NETDEV_TX_OK you must free the packet up, either
immediately or in response to the TX interrupt which finishes the
sending of the TX packet.
The case where you aren't getting this right:
+ /* If it's still above 6 we can't do anything */
+ if (skb_shinfo(skb)->nr_frags > 6) {
+ dev_err(&vptr->pdev->dev,
+ "via-velocity: more than 6 frags, can't send.\n");
+ return NETDEV_TX_OK;
+ }
is bogus because you just did __skb_linearize() and it returned zero, therefore
it would be illegal to see ->nr_frags with a > 6 value here.
Just remove this check and block of code entirely.
^ permalink raw reply
* Re: [rfc 2/3 v2] [E1000-devel] [rfc 3/4] igb: Common error path in igb_init_vfs()
From: Simon Horman @ 2009-11-25 23:27 UTC (permalink / raw)
To: Alexander Duyck
Cc: e1000-devel@lists.sourceforge.net, netdev@vger.kernel.org,
Arnd Bergmann, Kirsher, Jeffrey T
In-Reply-To: <4B0DB12C.3030709@intel.com>
On Wed, Nov 25, 2009 at 02:35:24PM -0800, Alexander Duyck wrote:
> Simon Horman wrote:
> >Drop out into an error path on error.
> >
> >This is a bit superfluous as things stand, though arguably
> >it already makes the code cleaner. But it should help things a lot
> >if igb_init_vfs() has a several things to unwind on error.
> >
> >This patch eliminates resetting adapter->vfs_allocated_count to 0
> >in the case where CONFIG_PCI_IOV is not set, because in that
> >case adapter->vfs_allocated_count can never be non-zero.
> >
> >Signed-off-by: Simon Horman <horms@verge.net.au>
> >
> >--- Thu, 05 Nov 2009 11:58:50 +1100
> >* Initial post
> >
> >Wed, 25 Nov 2009 16:44:15 +1100
> >* Merged with " Initialise adapter->vfs_allocated_count in igb_init_vf()",
> > however the initialisation of adapter->vfs_allocated_count is no
> > longer moved into igb_init_vf() as doing so results in a panic.
> >
> >Index: net-next-2.6/drivers/net/igb/igb_main.c
> >===================================================================
> >--- net-next-2.6.orig/drivers/net/igb/igb_main.c 2009-11-25 17:05:43.000000000 +1100
> >+++ net-next-2.6/drivers/net/igb/igb_main.c 2009-11-25 17:05:44.000000000 +1100
> >@@ -1753,38 +1753,37 @@ static void __devinit igb_init_vf(struct
> > {
> > #ifdef CONFIG_PCI_IOV
> > struct pci_dev *pdev = adapter->pdev;
> >+ unsigned char mac_addr[ETH_ALEN];
> >+ int i;
> > if (adapter->vfs_allocated_count > 7)
> > adapter->vfs_allocated_count = 7;
> >- if (adapter->vfs_allocated_count) {
> >- adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
> >- sizeof(struct vf_data_storage),
> >- GFP_KERNEL);
> >- /* if allocation failed then we do not support SR-IOV */
> >- if (!adapter->vf_data) {
> >- adapter->vfs_allocated_count = 0;
> >- dev_err(&pdev->dev, "Unable to allocate memory for VF "
> >- "Data Storage\n");
> >- }
> >+ adapter->vf_data = kcalloc(adapter->vfs_allocated_count,
> >+ sizeof(struct vf_data_storage), GFP_KERNEL);
> >+ /* if allocation failed then we do not support SR-IOV */
> >+ if (!adapter->vf_data) {
> >+ dev_err(&pdev->dev, "Unable to allocate memory for VF "
> >+ "Data Storage\n");
> >+ goto err_zero;
> > }
> The only issue I see with the changes above is that if SR-IOV is not
> enabled via the max_vfs option you will end up returning an error
> even though there is nothing wrong. You might want to go and keep
> the if statement near the start and do something like:
> if (!adapter->vfs_allocated_count)
> goto err_zero;
>
> This way you can avoid the false error report.
Good idea, I will add that.
> >- if (pci_enable_sriov(pdev, adapter->vfs_allocated_count)) {
> >- kfree(adapter->vf_data);
> >- adapter->vf_data = NULL;
> >-#endif /* CONFIG_PCI_IOV */
> >- adapter->vfs_allocated_count = 0;
> >-#ifdef CONFIG_PCI_IOV
> >- } else {
> >- unsigned char mac_addr[ETH_ALEN];
> >- int i;
> >- dev_info(&pdev->dev, "%d vfs allocated\n",
> >- adapter->vfs_allocated_count);
> >- for (i = 0; i < adapter->vfs_allocated_count; i++) {
> >- random_ether_addr(mac_addr);
> >- igb_set_vf_mac(adapter, i, mac_addr);
> >- }
> >+ if (pci_enable_sriov(pdev, adapter->vfs_allocated_count))
> >+ goto err_free;
> >+
> >+ dev_info(&pdev->dev, "%d vfs allocated\n",
> >+ adapter->vfs_allocated_count);
> >+ for (i = 0; i < adapter->vfs_allocated_count; i++) {
> >+ random_ether_addr(mac_addr);
> >+ igb_set_vf_mac(adapter, i, mac_addr);
> > }
> >+
> >+ return;
> >+err_free:
> >+ kfree(adapter->vf_data);
> >+err_zero:
> >+ adapter->vf_data = NULL;
> >+ adapter->vfs_allocated_count = 0;
> > #endif /* CONFIG_PCI_IOV */
> > }
> >
>
> My preference here would be to bump the #endif up two lines so that
> adapter->vf_data = NULL and adapter->vfs_allocated_count = 0 are ran
> in the non-iov case. That way we know that SR-IOV is explicitly
> disabled.
I'm not sure that its necessary but it certainly does seem to be
a clean and safe way to handle things. I'll update the patch.
^ 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