* nfs41: potential null deref in xprt_reserve_xprt()?
From: Dan Carpenter @ 2010-04-23 12:00 UTC (permalink / raw)
To: iyer-HgOvQuBEEgTQT0dZR+AlfA
Cc: linux-nfs-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA
I'm going through some Smatch results and had a question.
Until commit 343952fa5a: "nfs41: Get the rpc_xprt * from the rpc_rqst
instead of the rpc_clnt." we assumed that "task->tk_rqstp" can be NULL.
But that patch dereferences it unconditionally.
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 0eea2bf..c144611 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -195,8 +195,8 @@ EXPORT_SYMBOL_GPL(xprt_load_transport);
*/
int xprt_reserve_xprt(struct rpc_task *task)
{
- struct rpc_xprt *xprt = task->tk_xprt;
struct rpc_rqst *req = task->tk_rqstp;
+ struct rpc_xprt *xprt = req->rq_xprt;
^^^^^^^^^^^^^
Can "req" be null here? The patch is a year old, so presumably it
isn't null very often.
If you would like, I can remove the checks for null from the rest of the
function.
regards,
dan carpenter
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH 1/7] Topcliff GbE: Add The Main code [3/3]
From: Masayuki Ohtake @ 2010-04-23 11:56 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
[-- Attachment #1: Type: message/partial, Size: 18536 bytes --]
^ permalink raw reply
* [PATCH 1/7] Topcliff GbE: Add The Main code [1/3]
From: Masayuki Ohtake @ 2010-04-23 11:56 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
[-- Attachment #1: Type: message/partial, Size: 39156 bytes --]
^ permalink raw reply
* [PATCH 1/7] Topcliff GbE: Add The Main code [2/3]
From: Masayuki Ohtake @ 2010-04-23 11:56 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
[-- Attachment #1: Type: message/partial, Size: 39085 bytes --]
^ permalink raw reply
* [PATCH 3/7] Topcliff GbE: Add The Ethtool code [2/2]
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
[-- Attachment #1: Type: message/partial, Size: 7634 bytes --]
^ permalink raw reply
* [PATCH 2/7] Topcliff GbE: Add The Parameter check code
From: Masayuki Ohtake @ 2010-04-23 11:59 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Andrew, Intel OTC
From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
This patch adds the Parameter check code of GbE driver for Topcliff.
The GbE driver needs all patch[1/7 to 7/7].
Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
drivers/net/pch_gbe/pch_gbe_param.c | 594 ++
+++++++++++++++++++++++++++++++ 1 files changed, 594 insertions(+)
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_param.c
topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_param.c
--- linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_param.c 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_param.c 2010-04-13
18:18:01.000000000 +0900
@@ -0,0 +1,594 @@
+/*!
+ * @file pch_gbe_param.c
+ * @brief Linux PCH Gigabit Ethernet Driver parameter check source file
+ *
+ * @version 1.00
+ *
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *
+ * created:
+ * OKI SEMICONDUCTOR 04/13/2010
+ * modified:
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+
+#include "pch_debug.h"
+#include "pch_gbe_osdep.h"
+#include "pch_gbe_defines.h"
+#include "pch_gbe_hw.h"
+#include "pch_gbe.h"
+
+/* This is the only thing that needs to be changed to adjust the
+ * maximum number of ports that the driver can manage.
+ */
+
+#define PCH_GBE_MAX_NIC 1
+
+#define OPTION_UNSET -1
+#define OPTION_DISABLED 0
+#define OPTION_ENABLED 1
+
+/* All parameters are treated the same, as an integer array of values.
+ * This macro just reduces the need to repeat the same declaration code
+ * over and over (plus this helps to avoid typo bugs).
+ */
+
+#define PCH_GBE_PARAM_INIT { [0 ... PCH_GBE_MAX_NIC] = OPTION_UNSET }
+#ifdef PCH_GBE_QAC
+#define PCH_GBE_PARAM(X, desc)
+#else
+#define PCH_GBE_PARAM(X, desc) \
+ static int X[PCH_GBE_MAX_NIC+1] = PCH_GBE_PARAM_INIT; \
+ static int num_##X; \
+ module_param_array_named(X, X, int, &num_##X, 0); \
+ MODULE_PARM_DESC(X, desc);
+#endif
+
+/*
+ * Transmit Descriptor Count
+ * Valid Range: PCH_GBE_MIN_TXD - PCH_GBE_MAX_TXD
+ * Default Value: PCH_GBE_DEFAULT_TXD
+ */
+PCH_GBE_PARAM(TxDescriptors, "Number of transmit descriptors");
+
+/*
+ * Receive Descriptor Count
+ * Valid Range: PCH_GBE_MIN_RXD - PCH_GBE_MAX_RXD
+ * Default Value: PCH_GBE_DEFAULT_RXD
+ */
+PCH_GBE_PARAM(RxDescriptors, "Number of receive descriptors");
+
+/* User Specified Speed Override
+ *
+ * Valid Range: 0, 10, 100, 1000
+ * - 0 - auto-negotiate at all supported speeds
+ * - 10 - only link at 10 Mbps
+ * - 100 - only link at 100 Mbps
+ * - 1000 - only link at 1000 Mbps
+ *
+ * Default Value: 0
+ */
+PCH_GBE_PARAM(Speed, "Speed setting");
+
+/* User Specified Duplex Override
+ *
+ * Valid Range: 0-2
+ * - 0 - auto-negotiate for duplex
+ * - 1 - only link at half duplex
+ * - 2 - only link at full duplex
+ *
+ * Default Value: 0
+ */
+PCH_GBE_PARAM(Duplex, "Duplex setting");
+
+/*
+ * Auto-negotiation Advertisement Override
+ * Valid Range: 0x01-0x0F, 0x20-0x2F
+ *
+ * The AutoNeg value is a bit mask describing which speed and duplex
+ * combinations should be advertised during auto-negotiation.
+ * The supported speed and duplex modes are listed below
+ *
+ * Bit 7 6 5 4 3 2 1 0
+ * Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10
+ * Duplex Full Full Half Full Half
+ *
+ * Default Value: 0x2F (copper)
+ */
+PCH_GBE_PARAM(AutoNeg, "Advertised auto-negotiation setting");
+#define AUTONEG_ADV_DEFAULT 0x2F
+
+/*
+ * User Specified Flow Control Override
+ * Valid Range: 0-3
+ * - 0 - No Flow Control
+ * - 1 - Rx only, respond to PAUSE frames but do not generate them
+ * - 2 - Tx only, generate PAUSE frames but ignore them on receive
+ * - 3 - Full Flow Control Support
+ * Default Value: Read flow control settings from the EEPROM
+ */
+PCH_GBE_PARAM(FlowControl, "Flow Control setting");
+
+/*
+ * XsumRX - Receive Checksum Offload Enable/Disable
+ * Valid Range: 0, 1
+ * - 0 - disables all checksum offload
+ * - 1 - enables receive IP/TCP/UDP checksum offload
+ * Default Value: PCH_GBE_DEFAULT_RX_CSUM
+ */
+PCH_GBE_PARAM(XsumRX, "Disable or enable Receive Checksum offload");
+
+/*
+ * XsumTX - Transmit Checksum Offload Enable/Disable
+ * Valid Range: 0, 1
+ * - 0 - disables all checksum offload
+ * - 1 - enables transmit IP/TCP/UDP checksum offload
+ * Default Value: PCH_GBE_DEFAULT_TX_CSUM
+ */
+PCH_GBE_PARAM(XsumTX, "Disable or enable Transmit Checksum offload");
+
+struct pch_gbe_option {
+ enum { enable_option, range_option, list_option } type;
+ signed char *name;
+ signed char *err;
+ int def;
+ union {
+ struct { /* range_option info */
+ int min;
+ int max;
+ } r;
+ struct { /* list_option info */
+ int nr;
+ struct pch_gbe_opt_list { int i; signed char *str; } *p;
+ } l;
+ } arg;
+};
+
+/* ------------------------------------------------------------------------
----
+ Function prototype
+---------------------------------------------------------------------------
- */
+static void pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter);
+static int pch_gbe_validate_option(int *value,
+ struct pch_gbe_option *opt,
+ struct pch_gbe_adapter *adapter);
+
+/* ------------------------------------------------------------------------
----
+ Function
+---------------------------------------------------------------------------
- */
+
+/*!
+ * @ingroup Linux driver internal function
+ * @fn static int pch_gbe_validate_option(int *value,
+ * struct pch_gbe_option *opt,
+ * struct pch_gbe_adapter
*adapter)
+ * @brief Validate option
+ * @param value [IN] value
+ * @param opt [IN] option
+ * @param adapter [IN] Board private structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ */
+static int
+pch_gbe_validate_option(int *value, struct pch_gbe_option *opt,
+ struct pch_gbe_adapter *adapter)
+{
+ if (*value == OPTION_UNSET) {
+ *value = opt->def;
+ return 0;
+ }
+
+ switch (opt->type) {
+ case enable_option:
+ switch (*value) {
+ case OPTION_ENABLED:
+ DPRINTK(PROBE, INFO, "%s Enabled\n", opt->name);
+ return 0;
+ case OPTION_DISABLED:
+ DPRINTK(PROBE, INFO, "%s Disabled\n", opt->name);
+ return 0;
+ }
+ break;
+ case range_option:
+ if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) {
+ DPRINTK(PROBE, INFO,
+ "%s set to %i\n", opt->name, *value);
+ return 0;
+ }
+ break;
+ case list_option: {
+ int i;
+ struct pch_gbe_opt_list *ent;
+
+ for (i = 0; i < opt->arg.l.nr; i++) {
+ ent = &opt->arg.l.p[i];
+ if (*value == ent->i) {
+ if (ent->str[0] != '\0')
+ DPRINTK(PROBE, INFO, "%s\n", ent->str);
+ return 0;
+ }
+ }
+ }
+ break;
+ default:
+ BUG();
+ }
+
+ DPRINTK(PROBE, INFO, "Invalid %s value specified (%i) %s\n",
+ opt->name, *value, opt->err);
+ *value = opt->def;
+ return -1;
+}
+
+/*!
+ * @ingroup Linux driver internal function
+ * @fn void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
+ * @brief Range Checking for Command Line Parameters
+ * @param adapter [IN] Board private structure
+ * @return None
+ * @remarks
+ * This routine checks all command line parameters for valid user
+ * input. If an invalid value is given, or if no user specified
+ * value exists, a default value is used. The final value is stored
+ * in a variable in the adapter structure.
+ */
+void
+pch_gbe_check_options(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ int bd = adapter->bd_number;
+
+ PCH_DEBUG("pch_gbe_check_options\n");
+
+ if (bd >= PCH_GBE_MAX_NIC) {
+ DPRINTK(PROBE, NOTICE,
+ "Warning: no configuration for board #%i\n", bd);
+ DPRINTK(PROBE, NOTICE, "Using defaults for all values\n");
+ }
+
+ { /* Transmit Descriptor Count */
+ struct pch_gbe_option opt = {
+ .type = range_option,
+ .name = "Transmit Descriptors",
+ .err = "using default of "
+ __MODULE_STRING(PCH_GBE_DEFAULT_TXD),
+ .def = PCH_GBE_DEFAULT_TXD,
+ .arg = { .r = { .min = PCH_GBE_MIN_TXD } },
+ .arg = { .r = { .max = PCH_GBE_MAX_TXD } }
+ };
+ struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
+ if (num_TxDescriptors > bd) {
+ tx_ring->count = TxDescriptors[bd];
+ pch_gbe_validate_option(&tx_ring->count, &opt, adapter);
+ PCH_GBE_ROUNDUP(tx_ring->count,
+ PCH_GBE_TX_DESC_MULTIPLE);
+ } else {
+ tx_ring->count = opt.def;
+ }
+ }
+ { /* Receive Descriptor Count */
+ struct pch_gbe_option opt = {
+ .type = range_option,
+ .name = "Receive Descriptors",
+ .err = "using default of "
+ __MODULE_STRING(PCH_GBE_DEFAULT_RXD),
+ .def = PCH_GBE_DEFAULT_RXD,
+ .arg = { .r = { .min = PCH_GBE_MIN_RXD } },
+ .arg = { .r = { .max = PCH_GBE_MAX_RXD } }
+ };
+ struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
+ if (num_RxDescriptors > bd) {
+ rx_ring->count = RxDescriptors[bd];
+ pch_gbe_validate_option(&rx_ring->count, &opt, adapter);
+ PCH_GBE_ROUNDUP(rx_ring->count,
+ PCH_GBE_RX_DESC_MULTIPLE);
+ } else {
+ rx_ring->count = opt.def;
+ }
+ }
+ { /* Checksum Offload Enable/Disable */
+ struct pch_gbe_option opt = {
+ .type = enable_option,
+ .name = "Checksum Offload",
+ .err = "defaulting to Enabled",
+ .def = PCH_GBE_DEFAULT_RX_CSUM
+ };
+
+ if (num_XsumRX > bd) {
+ adapter->rx_csum = XsumRX[bd];
+ pch_gbe_validate_option((int *)(&adapter->rx_csum),
+ &opt, adapter);
+ } else {
+ adapter->rx_csum = opt.def;
+ }
+ }
+ { /* Checksum Offload Enable/Disable */
+ struct pch_gbe_option opt = {
+ .type = enable_option,
+ .name = "Checksum Offload",
+ .err = "defaulting to Enabled",
+ .def = PCH_GBE_DEFAULT_TX_CSUM
+ };
+
+ if (num_XsumTX > bd) {
+ adapter->tx_csum = XsumTX[bd];
+ pch_gbe_validate_option((int *)(&adapter->tx_csum),
+ &opt, adapter);
+ } else {
+ adapter->tx_csum = opt.def;
+ }
+ }
+ { /* Flow Control */
+
+ struct pch_gbe_opt_list fc_list[] = {
+ {pch_gbe_fc_none, "Flow Control Disabled"},
+ {pch_gbe_fc_rx_pause, "Flow Control Receive Only"},
+ {pch_gbe_fc_tx_pause, "Flow Control Transmit Only"},
+ {pch_gbe_fc_full, "Flow Control Enabled"} };
+
+ struct pch_gbe_option opt = {
+ .type = list_option,
+ .name = "Flow Control",
+ .err = "reading default settings from EEPROM",
+ .def = PCH_GBE_FC_DEFAULT,
+ .arg = { .l = { .nr = (int)ARRAY_SIZE(fc_list),
+ .p = fc_list } }
+ };
+
+ if (num_FlowControl > bd) {
+ hw->mac.fc = FlowControl[bd];
+ pch_gbe_validate_option((int *)(&hw->mac.fc),
+ &opt, adapter);
+ } else {
+ hw->mac.fc = opt.def;
+ }
+ }
+
+ pch_gbe_check_copper_options(adapter);
+}
+
+/*!
+ * @ingroup Linux driver internal function
+ * @fn static void pch_gbe_check_copper_options(
+ * struct pch_gbe_adapter *adapter)
+ * @brief Range Checking for Link Options, Copper Version
+ * @param adapter [IN] Board private structure
+ * @return None
+ * @remarks
+ * Handles speed and duplex options on copper adapters
+ */
+static void
+pch_gbe_check_copper_options(struct pch_gbe_adapter *adapter)
+{
+ struct pch_gbe_hw *hw = &adapter->hw;
+ int speed, dplx;
+ int bd = adapter->bd_number;
+
+ { /* Speed */
+ struct pch_gbe_opt_list speed_list[] = {
+ {0, "" },
+ {SPEED_10, ""},
+ {SPEED_100, ""},
+ {SPEED_1000, ""} };
+
+ struct pch_gbe_option opt = {
+ .type = list_option,
+ .name = "Speed",
+ .err = "parameter ignored",
+ .def = 0,
+ .arg = { .l = { .nr = (int)ARRAY_SIZE(speed_list),
+ .p = speed_list } }
+ };
+
+ if (num_Speed > bd) {
+ speed = Speed[bd];
+ pch_gbe_validate_option(&speed, &opt, adapter);
+ } else {
+ speed = opt.def;
+ }
+ }
+ { /* Duplex */
+ struct pch_gbe_opt_list dplx_list[] = {
+ {0, ""},
+ {PHY_HALF_DUPLEX, ""},
+ {PHY_FULL_DUPLEX, ""} };
+
+ struct pch_gbe_option opt = {
+ .type = list_option,
+ .name = "Duplex",
+ .err = "parameter ignored",
+ .def = 0,
+ .arg = { .l = { .nr = (int)ARRAY_SIZE(dplx_list),
+ .p = dplx_list } }
+ };
+
+ if (num_Duplex > bd) {
+ dplx = Duplex[bd];
+ pch_gbe_validate_option(&dplx, &opt, adapter);
+ } else {
+ dplx = opt.def;
+ }
+ }
+
+ { /* Autoneg */
+ struct pch_gbe_opt_list an_list[] =
+ #define AA "AutoNeg advertising "
+ {{ 0x01, AA "10/HD" },
+ { 0x02, AA "10/FD" },
+ { 0x03, AA "10/FD, 10/HD" },
+ { 0x04, AA "100/HD" },
+ { 0x05, AA "100/HD, 10/HD" },
+ { 0x06, AA "100/HD, 10/FD" },
+ { 0x07, AA "100/HD, 10/FD, 10/HD" },
+ { 0x08, AA "100/FD" },
+ { 0x09, AA "100/FD, 10/HD" },
+ { 0x0a, AA "100/FD, 10/FD" },
+ { 0x0b, AA "100/FD, 10/FD, 10/HD" },
+ { 0x0c, AA "100/FD, 100/HD" },
+ { 0x0d, AA "100/FD, 100/HD, 10/HD" },
+ { 0x0e, AA "100/FD, 100/HD, 10/FD" },
+ { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" },
+ { 0x20, AA "1000/FD" },
+ { 0x21, AA "1000/FD, 10/HD" },
+ { 0x22, AA "1000/FD, 10/FD" },
+ { 0x23, AA "1000/FD, 10/FD, 10/HD" },
+ { 0x24, AA "1000/FD, 100/HD" },
+ { 0x25, AA "1000/FD, 100/HD, 10/HD" },
+ { 0x26, AA "1000/FD, 100/HD, 10/FD" },
+ { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" },
+ { 0x28, AA "1000/FD, 100/FD" },
+ { 0x29, AA "1000/FD, 100/FD, 10/HD" },
+ { 0x2a, AA "1000/FD, 100/FD, 10/FD" },
+ { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" },
+ { 0x2c, AA "1000/FD, 100/FD, 100/HD" },
+ { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" },
+ { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" },
+ { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" } };
+
+ struct pch_gbe_option opt = {
+ .type = list_option,
+ .name = "AutoNeg",
+ .err = "parameter ignored",
+ .def = AUTONEG_ADV_DEFAULT,
+ .arg = { .l = { .nr = (int)ARRAY_SIZE(an_list),
+ .p = an_list} }
+ };
+
+ if (num_AutoNeg > bd) {
+ if (speed != 0 || dplx != 0) {
+ DPRINTK(PROBE, INFO,
+ "AutoNeg specified along with Speed or Duplex, "
+ "parameter ignored\n");
+ hw->phy.autoneg_advertised = opt.def;
+ } else {
+ hw->phy.autoneg_advertised = AutoNeg[bd];
+ pch_gbe_validate_option(
+ (int *)(&hw->phy.autoneg_advertised),
+ &opt, adapter);
+ }
+ } else {
+ hw->phy.autoneg_advertised = opt.def;
+ }
+ }
+
+ switch (speed + dplx) {
+ case 0:
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ if ((num_Speed > bd) && (speed != 0 || dplx != 0))
+ DPRINTK(PROBE, INFO,
+ "Speed and duplex autonegotiation enabled\n");
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case PHY_HALF_DUPLEX:
+ DPRINTK(PROBE, INFO, "Half Duplex specified without Speed\n");
+ DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+ "Half Duplex only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
+ PHY_ADVERTISE_100_HALF;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case PHY_FULL_DUPLEX:
+ DPRINTK(PROBE, INFO, "Full Duplex specified without Speed\n");
+ DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+ "Full Duplex only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_10_FULL |
+ PHY_ADVERTISE_100_FULL |
+ PHY_ADVERTISE_1000_FULL;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_FULL;
+ break;
+ case PHY_SPEED_10:
+ DPRINTK(PROBE, INFO, "10 Mbps Speed specified "
+ "without Duplex\n");
+ DPRINTK(PROBE, INFO, "Using Autonegotiation at 10 Mbps only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_10_HALF |
+ PHY_ADVERTISE_10_FULL;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case PHY_SPEED_10 + PHY_HALF_DUPLEX:
+ DPRINTK(PROBE, INFO, "Forcing to 10 Mbps Half Duplex\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+ hw->phy.autoneg_advertised = 0;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case PHY_SPEED_10 + PHY_FULL_DUPLEX:
+ DPRINTK(PROBE, INFO, "Forcing to 10 Mbps Full Duplex\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+ hw->phy.autoneg_advertised = 0;
+ hw->mac.link_speed = SPEED_10;
+ hw->mac.link_duplex = DUPLEX_FULL;
+ break;
+ case PHY_SPEED_100:
+ DPRINTK(PROBE, INFO, "100 Mbps Speed specified "
+ "without Duplex\n");
+ DPRINTK(PROBE, INFO, "Using Autonegotiation at "
+ "100 Mbps only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_100_HALF |
+ PHY_ADVERTISE_100_FULL;
+ hw->mac.link_speed = SPEED_100;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case PHY_SPEED_100 + PHY_HALF_DUPLEX:
+ DPRINTK(PROBE, INFO, "Forcing to 100 Mbps Half Duplex\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+ hw->phy.autoneg_advertised = 0;
+ hw->mac.link_speed = SPEED_100;
+ hw->mac.link_duplex = DUPLEX_HALF;
+ break;
+ case PHY_SPEED_100 + PHY_FULL_DUPLEX:
+ DPRINTK(PROBE, INFO, "Forcing to 100 Mbps Full Duplex\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 0;
+ hw->phy.autoneg_advertised = 0;
+ hw->mac.link_speed = SPEED_100;
+ hw->mac.link_duplex = DUPLEX_FULL;
+ break;
+ case PHY_SPEED_1000:
+ DPRINTK(PROBE, INFO, "1000 Mbps Speed specified without "
+ "Duplex\n");
+ goto full_duplex_only;
+ case PHY_SPEED_1000 + PHY_HALF_DUPLEX:
+ DPRINTK(PROBE, INFO,
+ "Half Duplex is not supported at 1000 Mbps\n");
+ /* fall through */
+ case PHY_SPEED_1000 + PHY_FULL_DUPLEX:
+full_duplex_only:
+ DPRINTK(PROBE, INFO,
+ "Using Autonegotiation at 1000 Mbps Full Duplex only\n");
+ hw->mac.autoneg = hw->mac.fc_autoneg = 1;
+ hw->phy.autoneg_advertised = PHY_ADVERTISE_1000_FULL;
+ hw->mac.link_speed = SPEED_1000;
+ hw->mac.link_duplex = DUPLEX_FULL;
+ break;
+ default:
+ BUG();
+ }
+}
+
^ permalink raw reply
* [PATCH 4/7] Topcliff GbE: Add The Hardware layer I/F code
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
This patch adds the Hardware layer I/F code of GbE driver for Topcliff.
The GbE driver needs all patch[1/7 to 7/7].
Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
drivers/net/pch_gbe/pch_gbe_api.c | 648 ++
drivers/net/pch_gbe/pch_gbe_api.h | 251
drivers/net/pch_gbe/pch_gbe_plat.c | 175
+++++++++++++++++++++++++++++++ 3 files changed, 1074 insertions(+)
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.c
topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.c
--- linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.c 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.c 2010-04-13
19:23:50.000000000 +0900
@@ -0,0 +1,648 @@
+/*!
+ * @file pch_gbe_api.c
+ * @brief Linux PCH Gigabit Ethernet Driver HAL API source file
+ *
+ * @version 1.00
+ *
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *
+ * created:
+ * OKI SEMICONDUCTOR 04/13/2010
+ * modified:
+ *
+ */
+
+#include "pch_debug.h"
+#include "pch_gbe_osdep.h"
+#include "pch_gbe_defines.h"
+#include "pch_gbe_hw.h"
+#include "pch_gbe_mac.h"
+#include "pch_gbe_api.h"
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_set_mac_type(struct pch_gbe_hw *hw)
+ * @brief Sets MAC type
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks This function sets the mac type of the adapter based on the
+ * device ID stored in the hw structure.
+ * MUST BE FIRST FUNCTION CALLED (explicitly or through
+ * pch_gbe_hal_setup_init_funcs()).
+ */
+s32 pch_gbe_hal_set_mac_type(struct pch_gbe_hw *hw)
+{
+ struct pch_gbe_mac_info *mac = &hw->mac;
+ s32 ret_val = PCH_GBE_SUCCESS;
+
+ PCH_DEBUG("pch_gbe_hal_set_mac_type\n");
+
+ switch ((u16) hw->device_id) {
+ case PCI_DEVICE_ID_INTEL_IOH1_GBE:
+ mac->type = PCH_GBE_MAC_TYPE_PCH1;
+ break;
+ default:
+ /* Should never have loaded on this device */
+ mac->type = PCH_GBE_MAC_TYPE_UNDEFINED;
+ ret_val = -PCH_GBE_ERR_MAC_INIT;
+ break;
+ }
+ PCH_DEBUG("mac->type:0x%x ret_val:0x%x\n", mac->type, ret_val);
+ return ret_val;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw)
+ * @brief Initializes function pointers
+ * @param hw [INOUT] pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks This function must be called by a driver in order to use the
rest
+ * of the 'shared' code files. Called by drivers only.
+ */
+s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw)
+{
+ s32 ret_val;
+
+ PCH_DEBUG("pch_gbe_hal_setup_init_funcs\n");
+
+ /* Can't do much good without knowing the MAC type.
+ */
+ ret_val = pch_gbe_hal_set_mac_type(hw);
+ if (ret_val) {
+ PCH_LOG(KERN_ERR,
+ "ERROR: MAC type could not be set properly.\n");
+ goto out;
+ }
+
+ if (!hw->hw_addr) {
+ PCH_LOG(KERN_ERR, "ERROR: Registers not mapped\n");
+ ret_val = -PCH_GBE_ERR_CONFIG;
+ goto out;
+ }
+
+ /* Set up the init function pointers. These are functions within the
+ * adapter family file that sets up function pointers for the rest of
+ * the functions in that family.
+ */
+ switch (hw->mac.type) {
+ case PCH_GBE_MAC_TYPE_PCH1:
+ case PCH_GBE_MAC_TYPE_PCH2:
+ pch_gbe_plat_init_function_pointers(hw);
+ break;
+ default:
+ PCH_LOG(KERN_ERR, "Hardware not supported\n");
+ ret_val = -PCH_GBE_ERR_CONFIG;
+ break;
+ }
+out:
+ PCH_DEBUG("ret_val:0x%x\n", ret_val);
+ return ret_val;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw)
+ * @brief Obtain bus information for adapter
+ * @param hw [INOUT] pointer to the HW structure
+ * @return None
+ * @remarks This will obtain information about the HW bus for which the
+ * adaper is attached and stores it in the hw structure. This is a
+ * function pointer entry point called by drivers.
+ */
+void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_get_bus_info\n");
+
+ if (hw->func.get_bus_info != NULL)
+ hw->func.get_bus_info(hw);
+ else
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_mc_addr_list_update(struct pch_gbe_hw *hw,
+ * u8 *mc_addr_list, u32 mc_addr_count,
+ * u32 mar_used_count, u32 mar_count)
+ * @brief Update Multicast addresses
+ * @param hw [INOUT] Pointer to the HW structure
+ * @param mc_addr_list [IN]Array of multicast addresses to program
+ * @param mc_addr_count [IN]Number of multicast addresses to program
+ * @param mar_used_count [IN]The first MAC Address register free to
program
+ * @param mar_count [IN]Total number of supported MAC Address Registers
+ * @return None
+ * @remarks
+ * Updates the MAC Address Registers and Multicast Table Array.
+ * The caller must have a packed mc_addr_list of multicast addresses.
+ * The parameter mar_count will usually be hw->mac.mar_entry_count
+ * unless there are workarounds that change this. Currently no func
pointer
+ * exists and all implementations are handled in the generic version of
this
+ * function.
+ */
+void
+pch_gbe_hal_mc_addr_list_update(struct pch_gbe_hw *hw,
+ u8 *mc_addr_list,
+ u32 mc_addr_count,
+ u32 mar_used_count, u32 mar_count)
+{
+ PCH_DEBUG("pch_gbe_hal_mc_addr_list_update\n");
+
+ if (hw->func.mc_addr_list_update != NULL) {
+ hw->func.mc_addr_list_update(hw,
+ mc_addr_list,
+ mc_addr_count,
+ mar_used_count, mar_count);
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_force_mac_fc(struct pch_gbe_hw *hw)
+ * @brief Force MAC flow control
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * Force the MAC's flow control settings. Currently no func pointer exists
+ * and all implementations are handled in the generic version of this
+ * function.
+ */
+s32 pch_gbe_hal_force_mac_fc(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_force_mac_fc\n");
+
+ return pch_gbe_mac_force_mac_fc(hw);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_reset_hw(struct pch_gbe_hw *hw)
+ * @brief Reset hardware
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * This resets the hardware into a known state. This is a function pointer
+ * entry point called by drivers.
+ */
+s32 pch_gbe_hal_reset_hw(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_reset_hw\n");
+
+ if (hw->func.reset_hw != NULL) {
+ hw->func.reset_hw(hw);
+ return PCH_GBE_SUCCESS;
+ } else {
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+ return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
+ * @brief Initialize hardware
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * This inits the hardware readying it for operation. This is a function
+ * pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_init_hw\n");
+
+ if (hw->func.init_hw != NULL) {
+ return hw->func.init_hw(hw);
+ } else {
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+ return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_setup_link(struct pch_gbe_hw *hw)
+ * @brief Configures link and flow control
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * This configures link and flow control settings for the adapter. This
+ * is a function pointer entry point called by drivers. While modules can
+ * also call this, they probably call their own version of this function.
+ */
+s32 pch_gbe_hal_setup_link(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_setup_link\n");
+
+ if (hw->func.setup_link != NULL) {
+ return hw->func.setup_link(hw);
+ } else {
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+ return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_setup_led(struct pch_gbe_hw *hw)
+ * @brief Configures SW controllable LED
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * This prepares the SW controllable LED for use and saves the current
state
+ * of the LED so it can be later restored. This is a function pointer
entry
+ * point called by drivers.
+ */
+s32 pch_gbe_hal_setup_led(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_setup_led\n");
+
+ if (hw->func.setup_led != NULL)
+ return hw->func.setup_led(hw);
+ else
+ return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_cleanup_led(struct pch_gbe_hw *hw)
+ * @brief Restores SW controllable LED
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * This restores the SW controllable LED to the value saved off by
+ * pch_gbe_hal_setup_led.
+ * This is a function pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_cleanup_led(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_cleanup_led\n");
+
+ if (hw->func.cleanup_led != NULL)
+ return hw->func.cleanup_led(hw);
+ else
+ return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_led_on(struct pch_gbe_hw *hw)
+ * @brief Turn on SW controllable LED
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * Turns the SW defined LED on. This is a function pointer entry point
+ * called by drivers.
+ */
+s32 pch_gbe_hal_led_on(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_led_on\n");
+
+ if (hw->func.led_on != NULL)
+ return hw->func.led_on(hw);
+ else
+ return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_led_off(struct pch_gbe_hw *hw)
+ * @brief Turn off SW controllable LED
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * Turns the SW defined LED off. This is a function pointer entry point
+ * called by drivers.
+ */
+s32 pch_gbe_hal_led_off(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_led_off\n");
+
+ if (hw->func.led_off != NULL)
+ return hw->func.led_off(hw);
+ else
+ return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_mar_set(struct pch_gbe_hw *hw, u8 *addr, u32
index)
+ * @brief Sets a MAC address register
+ * @param hw [INOUT] Pointer to the HW structure
+ * @param addr [IN] Address to set the RAR to
+ * @param index [IN] The RAR to set
+ * @return None
+ * @remarks
+ * Sets a MAC Address Register (RAR) to the specified address.
+ * Currently no func pointer exists and all implementations are
+ * handled in the generic version of this function.
+ */
+void pch_gbe_hal_mar_set(struct pch_gbe_hw *hw, u8 *addr, u32 index)
+{
+ PCH_DEBUG("pch_gbe_hal_mar_set\n");
+
+ pch_gbe_mac_mar_set(hw, addr, index);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw,
+ * u32 offset, u16 *data)
+ * @brief Reads PHY register
+ * @param hw [INOUT] Pointer to the HW structure
+ * @param offset [IN] The register to read
+ * @param data [IN] The buffer to store the 16-bit read.
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * Reads the PHY register and returns the value in data.
+ * This is a function pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 *data)
+{
+ PCH_DEBUG("pch_gbe_hal_read_phy_reg\n");
+
+ if (hw->func.read_phy_reg != NULL)
+ return hw->func.read_phy_reg(hw, offset, data);
+ else
+ return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw,
+ * u32 offset, u16 data)
+ * @brief Writes PHY register
+ * @param hw [INOUT] Pointer to the HW structure
+ * @param offset [IN] The register to write
+ * @param data [IN] The value to write.
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * Writes the PHY register at offset with the value in data.
+ * This is a function pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 data)
+{
+ PCH_DEBUG("pch_gbe_hal_write_phy_reg\n");
+
+ if (hw->func.write_phy_reg != NULL)
+ return hw->func.write_phy_reg(hw, offset, data);
+ else
+ return PCH_GBE_SUCCESS;
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
+ * @brief Hard PHY reset
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return None
+ * @remarks
+ * Performs a hard PHY reset. This is a function pointer entry point
called
+ * by drivers.
+ */
+void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_phy_hw_reset\n");
+
+ if (hw->func.reset_phy != NULL)
+ hw->func.reset_phy(hw);
+ else
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
+ * @brief Soft PHY reset
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return None
+ * @remarks
+ * Performs a soft PHY reset on those that apply. This is a function
pointer
+ * entry point called by drivers.
+ */
+void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_phy_sw_reset\n");
+
+ if (hw->func.sw_reset_phy != NULL)
+ hw->func.sw_reset_phy(hw);
+ else
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
+ * @brief Reads MAC address
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * Reads the MAC address out of the adapter and stores it in the HW
structure.
+ * Currently no func pointer exists and all implementations are handled in
the
+ * generic version of this function.
+ */
+s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_read_mac_addr\n");
+
+ if (hw->func.read_mac_addr != NULL) {
+ return hw->func.read_mac_addr(hw);
+ } else {
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+ return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+#ifdef CONFIG_PCH_PHUB
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_validate_nvm_checksum(struct pch_gbe_hw *hw)
+ * @brief Verifies NVM (EEPROM) checksum
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * Validates the NVM checksum is correct. This is a function pointer entry
+ * point called by drivers.
+ */
+s32 pch_gbe_hal_validate_nvm_checksum(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_validate_nvm_checksum\n");
+
+ if (hw->func.validate_nvm != NULL) {
+ return hw->func.validate_nvm(hw);
+ } else {
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+ return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_read_nvm(struct pch_gbe_hw *hw,
+ * u32 offset, u8 *data)
+ * @brief Reads NVM (EEPROM)
+ * @param hw [INOUT] Pointer to the HW structure
+ * @param offset [IN] The word offset to read
+ * @param data [IN] Pointer to the properly sized buffer for the data.
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * Reads 16-bit chunks of data from the NVM (EEPROM). This is a function
+ * pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_read_nvm(struct pch_gbe_hw *hw, u32 offset, u8 *data)
+{
+ PCH_DEBUG("pch_gbe_hal_read_nvm\n");
+
+ if (hw->func.read_nvm != NULL) {
+ return hw->func.read_nvm(hw, offset, data);
+ } else {
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+ return -PCH_GBE_ERR_CONFIG;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_write_nvm(struct pch_gbe_hw *hw,
+ * u32 offset, u8 *data)
+ * @brief Writes to NVM (EEPROM)
+ * @param hw [INOUT] Pointer to the HW structure
+ * @param offset [IN] The word offset to read
+ * @param data [IN] Pointer to the properly sized buffer for the data.
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * Writes 16-bit chunks of data to the NVM (EEPROM). This is a function
+ * pointer entry point called by drivers.
+ */
+s32 pch_gbe_hal_write_nvm(struct pch_gbe_hw *hw, u32 offset, u8 *data)
+{
+ PCH_DEBUG("pch_gbe_hal_write_nvm\n");
+
+ if (hw->func.write_nvm != NULL)
+ return hw->func.write_nvm(hw, offset, data);
+ else
+ return PCH_GBE_SUCCESS;
+}
+#endif /* CONFIG_PCH_PHUB */
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_set_wol_event(struct pch_gbe_hw *hw, u32
wu_evt)
+ * @brief Set wake-on-lan event
+ * @param hw [INOUT] Pointer to the HW structure
+ * @param wu_evt [IN] Wake up event
+ * @return None
+ */
+void pch_gbe_hal_set_wol_event(struct pch_gbe_hw *hw, u32 wu_evt)
+{
+ PCH_DEBUG("pch_gbe_hal_set_wol_event\n");
+
+ pch_gbe_mac_set_wol_event(hw, wu_evt);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
+ * @brief Power up PHY
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return None
+ */
+void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_power_up_phy\n");
+
+ if (hw->func.power_up_phy != NULL)
+ hw->func.power_up_phy(hw);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
+ * @brief Power down PHY
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return None
+ */
+void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_power_down_phy\n");
+
+ if (hw->func.power_down_phy != NULL)
+ hw->func.power_down_phy(hw);
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn u16 pch_gbe_hal_ctrl_miim(struct pch_gbe_hw *hw,
+ * u32 addr, u32 dir, u32 reg, u16 data)
+ * @brief Control MII Management IF
+ * @param hw [INOUT] Pointer to the HW structure
+ * @param addr [IN] Address of PHY
+ * @param dir [IN] Operetion. (Write or Read)
+ * @param reg [IN] Access register of PHY
+ * @param data [IN] Write data
+ * @return None
+ */
+u16
+pch_gbe_hal_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32 reg,
+ u16 data)
+{
+#ifdef DEBUG_TEST
+ PCH_DEBUG("pch_gbe_hal_ctrl_miim\n");
+#endif
+ if (hw->func.ctrl_miim != NULL) {
+ return hw->func.ctrl_miim(hw, addr, dir, reg, data);
+ } else {
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+ return PCH_GBE_SUCCESS;
+ }
+}
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_set_pause_packet(struct pch_gbe_hw *hw)
+ * @brief Set pause packet
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return None
+ */
+void pch_gbe_hal_set_pause_packet(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_hal_set_pause_packet\n");
+
+ if (hw->func.pause_packet != NULL)
+ hw->func.pause_packet(hw);
+ else
+ PCH_LOG(KERN_ERR, "Error: configuration\n");
+}
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.h
topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.h
--- linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.h 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_api.h 2010-04-13
19:25:22.000000000 +0900
@@ -0,0 +1,251 @@
+/*!
+ * @file pch_gbe_api.h
+ * @brief Linux PCH Gigabit Ethernet Driver HAL API header file
+ *
+ * @version 1.00
+ *
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *
+ * created:
+ * OKI SEMICONDUCTOR 04/13/2010
+ * modified:
+ *
+ */
+
+#ifndef _PCH_GBE_API_H_
+#define _PCH_GBE_API_H_
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_set_mac_type(struct pch_gbe_hw *hw)
+ * @brief Sets MAC type
+ */
+s32 pch_gbe_hal_set_mac_type(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw)
+ * @brief Initializes function pointers
+ */
+s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw)
+ * @brief Obtain bus information for adapter
+ */
+void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_mc_addr_list_update(struct pch_gbe_hw *hw,
+ * u8 *mc_addr_list, u32 mc_addr_count,
+ * u32 mar_used_count, u32 mar_count)
+ * @brief Update Multicast addresses
+ */
+void pch_gbe_hal_mc_addr_list_update(struct pch_gbe_hw *hw,
+ u8 *mc_addr_list, u32 mc_addr_count,
+ u32 mar_used_count, u32 mar_count);
+
+/*
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_force_mac_fc(struct pch_gbe_hw *hw)
+ * @brief Force MAC flow control
+ */
+s32 pch_gbe_hal_force_mac_fc(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_reset_hw(struct pch_gbe_hw *hw)
+ * @brief Reset hardware
+ */
+s32 pch_gbe_hal_reset_hw(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
+ * @brief Initialize hardware
+ */
+s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_setup_link(struct pch_gbe_hw *hw)
+ * @brief Configures link and flow control
+ */
+s32 pch_gbe_hal_setup_link(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_setup_led(struct pch_gbe_hw *hw)
+ * @brief Configures SW controllable LED
+ */
+s32 pch_gbe_hal_setup_led(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_cleanup_led(struct pch_gbe_hw *hw)
+ * @brief Restores SW controllable LED
+ */
+s32 pch_gbe_hal_cleanup_led(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_led_on(struct pch_gbe_hw *hw)
+ * @brief Turn on SW controllable LED
+ */
+s32 pch_gbe_hal_led_on(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_led_off(struct pch_gbe_hw *hw)
+ * @brief Turn off SW controllable LED
+ */
+s32 pch_gbe_hal_led_off(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_mar_set(struct pch_gbe_hw *hw, u8 *addr, u32
index)
+ * @brief Sets a MAC address register
+ */
+void pch_gbe_hal_mar_set(struct pch_gbe_hw *hw, u8 *addr, u32 index);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw,
+ * u32 offset, u16 *data)
+ * @brief Reads PHY register
+ */
+s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 *data);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw,
+ * u32 offset, u16 data)
+ * @brief Writes PHY register
+ */
+s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset, u16 data);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
+ * @brief Hard PHY reset
+ */
+void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
+ * @brief Soft PHY reset
+ */
+void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
+ * @brief Reads MAC address
+ */
+s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw);
+
+#ifdef CONFIG_PCH_PHUB
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_validate_nvm_checksum(struct pch_gbe_hw *hw)
+ * @brief Verifies NVM (EEPROM) checksum
+ */
+s32 pch_gbe_hal_validate_nvm_checksum(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_read_nvm(struct pch_gbe_hw *hw,
+ * u32 offset, u8 *data)
+ * @brief Reads NVM (EEPROM)
+ */
+s32 pch_gbe_hal_read_nvm(struct pch_gbe_hw *hw, u32 offset, u8 *data);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn s32 pch_gbe_hal_write_nvm(struct pch_gbe_hw *hw,
+ * u32 offset, u8 *data)
+ * @brief Writes to NVM (EEPROM)
+ */
+s32 pch_gbe_hal_write_nvm(struct pch_gbe_hw *hw, u32 offset, u8 *data);
+#endif /* CONFIG_PCH_PHUB */
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_set_wol_event(struct pch_gbe_hw *hw, u32
wu_evt)
+ * @brief Set wake-on-lan event
+ */
+void pch_gbe_hal_set_wol_event(struct pch_gbe_hw *hw, u32 wu_evt);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
+ * @brief Power up PHY
+ */
+void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
+ * @brief Power down PHY
+ */
+void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn u16 pch_gbe_hal_ctrl_miim(struct pch_gbe_hw *hw,
+ * u32 addr, u32 dir, u32 reg, u16 data)
+ * @brief Control MII Management IF
+ */
+u16 pch_gbe_hal_ctrl_miim(struct pch_gbe_hw *hw, u32 addr, u32 dir, u32
reg,
+ u16 data);
+
+/*!
+ * @ingroup HAL API Layer
+ * @fn void pch_gbe_hal_set_pause_packet(struct pch_gbe_hw *hw)
+ * @brief Set pause packet
+ */
+void pch_gbe_hal_set_pause_packet(struct pch_gbe_hw *hw);
+
+/*!
+ * @ingroup HAL API Layer
+ * @def PCH_GBE_HAL_MIIM_READ
+ * @brief Read operation is done through MII Management IF
+ */
+#define PCH_GBE_HAL_MIIM_READ ((u32)0x00000000)
+
+/*!
+ * @ingroup HAL API Layer
+ * @def PCH_GBE_HAL_MIIM_WRITE
+ * @brief Write operation is done through MII Management IF
+ */
+#define PCH_GBE_HAL_MIIM_WRITE ((u32)0x04000000)
+
+/* pch_gbe_plat.c */
+/*!
+ * @ingroup HAL internal functions
+ * @fn void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw)
+ * @brief Init func ptrs.
+ */
+void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw);
+
+#endif
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_plat.c
topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_plat.c
--- linux-2.6.33.1/drivers/net/pch_gbe/pch_gbe_plat.c 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/pch_gbe_plat.c 2010-04-13
19:25:07.000000000 +0900
@@ -0,0 +1,175 @@
+/*!
+ * @file pch_gbe_plat.c
+ * @brief Linux PCH Gigabit Ethernet Driver HAL internal function
(platform) source file
+ *
+ * @version 1.00
+ *
+ * @section
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
USA.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
+ *
+ * created:
+ * OKI SEMICONDUCTOR 04/13/2010
+ * modified:
+ *
+ */
+
+#include "pch_debug.h"
+#include "pch_gbe_osdep.h"
+#include "pch_gbe_defines.h"
+#include "pch_gbe_hw.h"
+#include "pch_gbe_mac.h"
+#include "pch_gbe_nvm.h"
+#include "pch_gbe_phy.h"
+#include "pch_gbe_api.h"
+
+
+static void pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw);
+static s32 pch_gbe_plat_init_hw(struct pch_gbe_hw *hw);
+
+
+/*!
+ * @ingroup HAL internal functions
+ * @fn void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw)
+ * @brief Init func ptrs.
+ * @param hw [OUT] Pointer to the HW structure
+ * @return None
+ * @remarks
+ * The only function explicitly called by the api module to initialize
+ * all function pointers and parameters.
+ */
+void
+pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw)
+{
+ struct pch_gbe_mac_info *mac = &hw->mac;
+ struct pch_gbe_phy_info *phy = &hw->phy;
+ struct pch_gbe_nvm_info *nvm = &hw->nvm;
+ struct pch_gbe_functions *func = &hw->func;
+
+ PCH_DEBUG("pch_gbe_plat_init_function_pointers\n");
+
+ /* Set MAC address registers entry count */
+ mac->mar_entry_count = PCH_GBE_MAR_ENTRIES;
+ /* Set PHY parameter */
+ phy->reset_delay_us = PCH_GBE_PHY_RESET_DELAY_US;
+ /* Set NVM parameter */
+ nvm->word_size = PCH_GBE_NVM_WORD_SIZE;
+
+ /* Set function pointers */
+ func->get_bus_info = pch_gbe_plat_get_bus_info;
+ func->reset_hw = pch_gbe_mac_reset_hw;
+ func->init_hw = pch_gbe_plat_init_hw;
+ func->setup_link = pch_gbe_mac_setup_link;
+ func->setup_physical_interface = pch_gbe_phy_setup_link_fpga;
+ func->mc_addr_list_update = pch_gbe_mac_mc_addr_list_update;
+ func->setup_led = pch_gbe_phy_led_setup;
+ func->cleanup_led = pch_gbe_phy_led_cleanup;
+ func->led_on = pch_gbe_phy_led_on;
+ func->led_off = pch_gbe_phy_led_off;
+ func->read_phy_reg = pch_gbe_phy_read_reg_miic;
+ func->write_phy_reg = pch_gbe_phy_write_reg_miic;
+ func->reset_phy = pch_gbe_phy_hw_reset;
+ func->sw_reset_phy = pch_gbe_phy_sw_reset;
+ func->power_up_phy = pch_gbe_phy_power_up;
+ func->power_down_phy = pch_gbe_phy_power_down;
+#ifdef CONFIG_PCH_PHUB
+ func->read_nvm = pch_gbe_nvm_read_mem;
+ func->write_nvm = pch_gbe_nvm_write_mem;
+ func->validate_nvm = pch_gbe_nvm_validate_checksum;
+ func->read_mac_addr = pch_gbe_nvm_read_mac_addr;
+#else
+ func->read_mac_addr = pch_gbe_mac_read_mac_addr;
+#endif
+ func->ctrl_miim = pch_gbe_mac_ctrl_miim;
+ func->pause_packet = pch_gbe_mac_set_pause_packet;
+
+#ifdef DEBUG_TEST
+ PCH_DEBUG("[MAC]mar_entry_count:%d /[PHY] reset_delay_us:%d\n",
+ mac->mar_entry_count, phy->reset_delay_us);
+ PCH_DEBUG("[NVM] word_size:0x%08x\n", nvm->word_size);
+#endif
+}
+
+
+/*!
+ * @ingroup HAL internal functions
+ * @fn static void pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw)
+ * @brief Obtain bus information for adapter
+ * @param hw [OUT] Pointer to the HW structure
+ * @return None
+ * @remarks
+ * This will obtain information about the HW bus for which the
+ * adaper is attached and stores it in the hw structure. This is a
function
+ * pointer entry point called by the api module.
+ */
+static void
+pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw)
+{
+ PCH_DEBUG("pch_gbe_plat_get_bus_info\n");
+
+ hw->bus.type = pch_gbe_bus_type_pci_express;
+ hw->bus.speed = pch_gbe_bus_speed_2500;
+ hw->bus.width = pch_gbe_bus_width_pcie_x1;
+
+#ifdef DEBUG_TEST
+ PCH_DEBUG("[BUS] type:0x%08x speed:0x%08x width:0x%08x\n",
+ hw->bus.type, hw->bus.speed, hw->bus.width);
+#endif
+}
+
+/*!
+ * @ingroup HAL internal functions
+ * @fn static s32 pch_gbe_plat_init_hw(struct pch_gbe_hw *hw)
+ * @brief Initialize hardware
+ * @param hw [INOUT] Pointer to the HW structure
+ * @return PCH_GBE_SUCCESS: Successfully
+ * @return Negative value: Failed
+ * @remarks
+ * This inits the hardware readying it for operation. This is a
+ * function pointer entry point called by the api module.
+ */
+static s32
+pch_gbe_plat_init_hw(struct pch_gbe_hw *hw)
+{
+ struct pch_gbe_mac_info *mac = &hw->mac;
+ s32 ret_val;
+
+ PCH_DEBUG("pch_gbe_plat_init_hw\n");
+
+ /* Setup the receive address. */
+ pch_gbe_mac_init_rx_addrs(hw, mac->mar_entry_count);
+
+ ret_val = pch_gbe_phy_get_id(hw);
+ if (ret_val) {
+ PCH_LOG(KERN_ERR, "pch_gbe_phy_get_id error\n");
+ return ret_val;
+ }
+ pch_gbe_phy_init_setting(hw);
+ /* Setup Mac interface option RGMII */
+#ifdef PCH_GBE_MAC_IFOP_RGMII
+ pch_gbe_phy_set_rgmii(hw);
+#endif
+ /* Setup link and flow control */
+ ret_val = pch_gbe_hal_setup_link(hw);
+#ifdef DEBUG_TEST
+ if (ret_val)
+ PCH_LOG(KERN_ERR, "pch_gbe_phy_get_id error\n");
+#endif
+ return ret_val;
+}
+
^ permalink raw reply
* [PATCH 3/7] Topcliff GbE: Add The Ethtool code [1/2]
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
[-- Attachment #1: Type: message/partial, Size: 39196 bytes --]
^ permalink raw reply
* [PATCH 5/7] Topcliff GbE: Add The Hardware layer codes [2/2]
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
[-- Attachment #1: Type: message/partial, Size: 9627 bytes --]
^ permalink raw reply
* [PATCH 5/7] Topcliff GbE: Add The Hardware layer codes [1/2]
From: Masayuki Ohtake @ 2010-04-23 12:00 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
[-- Attachment #1: Type: message/partial, Size: 39112 bytes --]
^ permalink raw reply
* [PATCH 6/7] Topcliff GbE: Add The common header files [2/2]
From: Masayuki Ohtake @ 2010-04-23 12:01 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
[-- Attachment #1: Type: message/partial, Size: 15960 bytes --]
^ permalink raw reply
* [PATCH 7/7] Topcliff GbE: Change The Kconfig and Makefile
From: Masayuki Ohtake @ 2010-04-23 12:01 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
This patch change the Kconfig and Makefile of GbE driver for Topcliff.
The GbE driver needs all patch[1/7 to 7/7].
Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
drivers/net/Kconfig | 5 ++
drivers/net/Makefile | 1
drivers/net/pch_gbe/Makefile | 6
+++++++++++++++++++++++++++++++ 3 files changed, 12 insertions(+)
diff -urN linux-2.6.33.1/drivers/net/Kconfig
topcliff-2.6.33.1/drivers/net/Kconfig
--- linux-2.6.33.1/drivers/net/Kconfig 2010-03-16 01:09:39.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/Kconfig 2010-04-13 00:55:22.000000000
+0900
@@ -1977,6 +1977,11 @@
If you say N, all options in this submenu will be skipped and disabled.
if NETDEV_1000
+config PCH_GBE
+ tristate "PCH Gigabit Ethernet"
+ ---help---
+ This is an gigabit ethernet driver for PCH.
+ resources.
config ACENIC
tristate "Alteon AceNIC/3Com 3C985/NetGear GA620 Gigabit support"
diff -urN linux-2.6.33.1/drivers/net/Makefile
topcliff-2.6.33.1/drivers/net/Makefile
--- linux-2.6.33.1/drivers/net/Makefile 2010-03-16 01:09:39.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/Makefile 2010-04-13 00:55:22.000000000
+0900
@@ -287,3 +287,4 @@
obj-$(CONFIG_WIMAX) += wimax/
obj-$(CONFIG_OCTEON_MGMT_ETHERNET) += octeon/
+obj-$(CONFIG_PCH_GBE) += pch_gbe/
diff -urN linux-2.6.33.1/drivers/net/pch_gbe/Makefile
topcliff-2.6.33.1/drivers/net/pch_gbe/Makefile
--- linux-2.6.33.1/drivers/net/pch_gbe/Makefile 1970-01-01
09:00:00.000000000 +0900
+++ topcliff-2.6.33.1/drivers/net/pch_gbe/Makefile 2010-04-13
00:55:22.000000000 +0900
@@ -0,0 +1,6 @@
+ifeq ($(CONFIG_PCH_GBE_DEBUG_CORE),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_PCH_GBE) += pch_gbe.o
+pch_gbe-objs := pch_gbe_mac.o pch_gbe_phy.o pch_gbe_nvm.o pch_gbe_ethtool.o
pch_gbe_plat.o pch_gbe_param.o pch_gbe_api.o pch_gbe_main.o
^ permalink raw reply
* [PATCH 6/7] Topcliff GbE: Add The common header files [1/2]
From: Masayuki Ohtake @ 2010-04-23 12:01 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew
[-- Attachment #1: Type: message/partial, Size: 39242 bytes --]
^ permalink raw reply
* Re: eSwitch management
From: Arnd Bergmann @ 2010-04-23 12:42 UTC (permalink / raw)
To: Anirban Chakraborty
Cc: Scott Feldman, David Miller, netdev@vger.kernel.org,
chrisw@redhat.com, Ameen Rahman, Amit Salecha, Rajesh Borundia
In-Reply-To: <DD92D5A8-1ECC-4440-BE81-ABDCC6847021@qlogic.com>
On Friday 23 April 2010, Anirban Chakraborty wrote:
> On Apr 22, 2010, at 6:29 PM, Scott Feldman wrote:
> > On 4/22/10 5:47 PM, "Scott Feldman" <scofeldm@cisco.com> wrote:
> >>
> >> Are any of these settings covered in DCB? (net/dcb/dcbnl.c). Maybe you can
> >> get a start there? Not sure not knowing your device requirements.
> >
> > Or maybe the RTM_SETLINK IFLA_VF_* ops in include/linux/if_link.h? Those
> > seem like what you're looking for. I'm looking at moving iovnl here as well
> > for port-profile.
>
> It looks like ifla_vf_info does contain most of the data set. But if I use it, what
> NETLINK protocol family should I use in my driver to receive netlink messages? Do I
> need to create a private protocol family?
Your driver should implement the ndo_set_vf_*/ndo_get_vf_* callbacks, not
implement the netlink protocol itself. If there is anything missing in the
existing callbacks that you require for the operation of your driver, you
should send patches to extend the implementation in net/core/rtnetlink.c.
Arnd
^ permalink raw reply
* Re: DDoS attack causing bad effect on conntrack searches
From: Jesper Dangaard Brouer @ 2010-04-23 12:45 UTC (permalink / raw)
To: Patrick McHardy
Cc: Eric Dumazet, Changli Gao, hawk, Linux Kernel Network Hackers,
netfilter-devel, Paul E McKenney
In-Reply-To: <4BD17CF9.4020502@trash.net>
On Fri, 23 Apr 2010, Patrick McHardy wrote:
> That sounds like a good idea. But lets what for Jesper's test results
> before we start fixing this problem :)
I will first have time to perform the tests Monday or Tuesday.
BUT I have just noticed there seems to be a corrolation between conntrack
early_drop and searches. I have upload a new graph:
http://people.netfilter.org/hawk/DDoS/2010-04-12__001/conntrack_early_drop002.png
I have not had time to checkout the code path yet...
Cheers,
Jesper Brouer
--
-------------------------------------------------------------------
MSc. Master of Computer Science
Dept. of Computer Science, University of Copenhagen
Author of http://www.adsl-optimizer.dk
-------------------------------------------------------------------
^ permalink raw reply
* Re: [PATCH] RCU: don't turn off lockdep when find suspicious rcu_dereference_check() usage
From: Miles Lane @ 2010-04-23 12:50 UTC (permalink / raw)
To: paulmck
Cc: Vivek Goyal, Eric Paris, Lai Jiangshan, Ingo Molnar,
Peter Zijlstra, LKML, nauman, eric.dumazet, netdev, Jens Axboe,
Gui Jianfeng, Li Zefan
In-Reply-To: <20100422160144.GC2524@linux.vnet.ibm.com>
Hi Paul,
There has been a bit of back and forth, and I am not sure what patches
I should test now.
Could you send me a bundle of whatever needs testing now?
I currently have a build of 2.6.34-rc5-git3 with the same patch I
tested before applied.
I notice a few minor differences in the warnings given. I suspect
these do not indicate
new issues, since the trace from <IRQ> through <EOI> is the same as before.
[ 60.174809] [ INFO: suspicious rcu_dereference_check() usage. ]
[ 60.174812] ---------------------------------------------------
[ 60.174816] net/mac80211/sta_info.c:886 invoked
rcu_dereference_check() without protection!
[ 60.174820]
[ 60.174821] other info that might help us debug this:
[ 60.174822]
[ 60.174825]
[ 60.174826] rcu_scheduler_active = 1, debug_locks = 1
[ 60.174829] no locks held by wpa_supplicant/3973.
[ 60.174832]
[ 60.174833] stack backtrace:
[ 60.174838] Pid: 3973, comm: wpa_supplicant Not tainted 2.6.34-rc5-git3 #19
[ 60.174841] Call Trace:
[ 60.174844] <IRQ> [<ffffffff81067faa>] lockdep_rcu_dereference+0x9d/0xa5
[ 60.174873] [<ffffffffa014e9ae>]
ieee80211_find_sta_by_hw+0x46/0x10f [mac80211]
[ 60.174886] [<ffffffffa014ea8e>] ieee80211_find_sta+0x17/0x19 [mac80211]
[ 60.174902] [<ffffffffa01a60f2>] iwl_tx_queue_reclaim+0xdb/0x1b1 [iwlcore]
[ 60.174909] [<ffffffff81068417>] ? mark_lock+0x2d/0x235
[ 60.174920] [<ffffffffa01d5f1c>] iwl5000_rx_reply_tx+0x4a9/0x556 [iwlagn]
[ 60.174927] [<ffffffff8120a2d3>] ? is_swiotlb_buffer+0x2e/0x3b
[ 60.174936] [<ffffffffa01cebf4>] iwl_rx_handle+0x163/0x2b5 [iwlagn]
[ 60.174943] [<ffffffff810688f0>] ? trace_hardirqs_on_caller+0xfa/0x13f
[ 60.174952] [<ffffffffa01cf3ac>] iwl_irq_tasklet+0x2bb/0x3c0 [iwlagn]
[ 60.174959] [<ffffffff810411df>] tasklet_action+0xa7/0x10f
[ 60.174965] [<ffffffff810421f1>] __do_softirq+0x144/0x252
[ 60.174972] [<ffffffff81003a8c>] call_softirq+0x1c/0x34
[ 60.174977] [<ffffffff810050e4>] do_softirq+0x38/0x80
[ 60.174982] [<ffffffff81041cbe>] irq_exit+0x45/0x94
[ 60.174987] [<ffffffff81004829>] do_IRQ+0xad/0xc4
[ 60.174994] [<ffffffff813cfb13>] ret_from_intr+0x0/0xf
[ 60.174997] <EOI> [<ffffffff810e5114>] ? kmem_cache_alloc+0xa9/0x15f
[ 60.175010] [<ffffffff81342182>] ? __alloc_skb+0x3d/0x155
[ 60.175016] [<ffffffff81342182>] __alloc_skb+0x3d/0x155
[ 60.175023] [<ffffffff8133d237>] sock_alloc_send_pskb+0xc0/0x2e5
[ 60.175030] [<ffffffff8133d46c>] sock_alloc_send_skb+0x10/0x12
[ 60.175036] [<ffffffff813b1ab5>] unix_stream_sendmsg+0x117/0x2e2
[ 60.175044] [<ffffffff811bdca8>] ? avc_has_perm+0x57/0x69
[ 60.175050] [<ffffffff8133b892>] ? sock_aio_write+0x0/0xcf
[ 60.175056] [<ffffffff813392c2>] __sock_sendmsg+0x59/0x64
[ 60.175062] [<ffffffff8133b94d>] sock_aio_write+0xbb/0xcf
[ 60.175069] [<ffffffff810e98b1>] do_sync_readv_writev+0xbc/0xfb
[ 60.175077] [<ffffffff811c1726>] ? selinux_file_permission+0xa2/0xaf
[ 60.175082] [<ffffffff810e9638>] ? copy_from_user+0x2a/0x2c
[ 60.175089] [<ffffffff811baf85>] ? security_file_permission+0x11/0x13
[ 60.175095] [<ffffffff810ea64e>] do_readv_writev+0xa2/0x122
[ 60.175101] [<ffffffff810ead3b>] ? fcheck_files+0x8f/0xc9
[ 60.175107] [<ffffffff810ea70c>] vfs_writev+0x3e/0x49
[ 60.175113] [<ffffffff810ea7f2>] sys_writev+0x45/0x8e
[ 60.175119] [<ffffffff81002b6b>] system_call_fastpath+0x16/0x1b
[ 60.223213] [ INFO: suspicious rcu_dereference_check() usage. ]
[ 60.223216] ---------------------------------------------------
[ 60.223221] net/mac80211/sta_info.c:886 invoked
rcu_dereference_check() without protection!
[ 60.223224]
[ 60.223225] other info that might help us debug this:
[ 60.223227]
[ 60.223230]
[ 60.223230] rcu_scheduler_active = 1, debug_locks = 1
[ 60.223234] no locks held by udisks-daemon/4398.
[ 60.223236]
[ 60.223237] stack backtrace:
[ 60.223242] Pid: 4398, comm: udisks-daemon Not tainted 2.6.34-rc5-git3 #19
[ 60.223245] Call Trace:
[ 60.223249] <IRQ> [<ffffffff81067faa>] lockdep_rcu_dereference+0x9d/0xa5
[ 60.223275] [<ffffffffa014e9fe>]
ieee80211_find_sta_by_hw+0x96/0x10f [mac80211]
[ 60.223288] [<ffffffffa014ea8e>] ieee80211_find_sta+0x17/0x19 [mac80211]
[ 60.223304] [<ffffffffa01a60f2>] iwl_tx_queue_reclaim+0xdb/0x1b1 [iwlcore]
[ 60.223310] [<ffffffff81068417>] ? mark_lock+0x2d/0x235
[ 60.223321] [<ffffffffa01d5f1c>] iwl5000_rx_reply_tx+0x4a9/0x556 [iwlagn]
[ 60.223329] [<ffffffff8120a2d3>] ? is_swiotlb_buffer+0x2e/0x3b
[ 60.223338] [<ffffffffa01cebf4>] iwl_rx_handle+0x163/0x2b5 [iwlagn]
[ 60.223344] [<ffffffff810688f0>] ? trace_hardirqs_on_caller+0xfa/0x13f
[ 60.223353] [<ffffffffa01cf3ac>] iwl_irq_tasklet+0x2bb/0x3c0 [iwlagn]
[ 60.223360] [<ffffffff810411df>] tasklet_action+0xa7/0x10f
[ 60.223367] [<ffffffff810421f1>] __do_softirq+0x144/0x252
[ 60.223374] [<ffffffff81003a8c>] call_softirq+0x1c/0x34
[ 60.223379] [<ffffffff810050e4>] do_softirq+0x38/0x80
[ 60.223384] [<ffffffff81041cbe>] irq_exit+0x45/0x94
[ 60.223389] [<ffffffff81004829>] do_IRQ+0xad/0xc4
[ 60.223396] [<ffffffff813cfb13>] ret_from_intr+0x0/0xf
[ 60.223399] <EOI> [<ffffffff810e34f1>] ? kmem_cache_free+0xb0/0x134
[ 60.223412] [<ffffffff810f391a>] ? putname+0x2d/0x36
[ 60.223417] [<ffffffff810f391a>] putname+0x2d/0x36
[ 60.223423] [<ffffffff810f5536>] user_path_at+0x5f/0x8e
[ 60.223429] [<ffffffff81068671>] ? mark_held_locks+0x52/0x70
[ 60.223435] [<ffffffff810e34ee>] ? kmem_cache_free+0xad/0x134
[ 60.223441] [<ffffffff8106890a>] ? trace_hardirqs_on_caller+0x114/0x13f
[ 60.223447] [<ffffffff81068942>] ? trace_hardirqs_on+0xd/0xf
[ 60.223454] [<ffffffff810ed93f>] vfs_fstatat+0x32/0x5d
[ 60.223460] [<ffffffff810ed9bb>] vfs_lstat+0x19/0x1b
[ 60.223465] [<ffffffff810ed9d7>] sys_newlstat+0x1a/0x38
[ 60.223471] [<ffffffff8106890a>] ? trace_hardirqs_on_caller+0x114/0x13f
[ 60.223477] [<ffffffff813cec00>] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 60.223485] [<ffffffff81002b6b>] system_call_fastpath+0x16/0x1b
^ permalink raw reply
* [PATCH] Topcliff PHUB: Add The Packet Hub driver [1/2]
From: Masayuki Ohtake @ 2010-04-23 13:49 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, NETDEV, andrew.chih.howe.khor
[-- Attachment #1: Type: message/partial, Size: 39163 bytes --]
^ permalink raw reply
* [PATCH] Topcliff PHUB: Add The Packet Hub driver [2/2]
From: Masayuki Ohtake @ 2010-04-23 13:49 UTC (permalink / raw)
To: NETDEV; +Cc: Wang, Yong Y, Wang, Qi, NETDEV, andrew.chih.howe.khor
[-- Attachment #1: Type: message/partial, Size: 27156 bytes --]
^ permalink raw reply
* Re: DDoS attack causing bad effect on conntrack searches
From: Patrick McHardy @ 2010-04-23 13:57 UTC (permalink / raw)
To: Jesper Dangaard Brouer
Cc: Eric Dumazet, Changli Gao, hawk, Linux Kernel Network Hackers,
netfilter-devel, Paul E McKenney
In-Reply-To: <Pine.LNX.4.64.1004231440190.840@ask.diku.dk>
Jesper Dangaard Brouer wrote:
> On Fri, 23 Apr 2010, Patrick McHardy wrote:
>
>> That sounds like a good idea. But lets what for Jesper's test results
>> before we start fixing this problem :)
>
> I will first have time to perform the tests Monday or Tuesday.
>
> BUT I have just noticed there seems to be a corrolation between
> conntrack early_drop and searches. I have upload a new graph:
>
> http://people.netfilter.org/hawk/DDoS/2010-04-12__001/conntrack_early_drop002.png
I guess that's somewhat expected when your conntrack table is full
and all you're seeing is new connection setup attempts.
First you have a search for an existing conntrack, then it attempts
to create a new one and tries to early_drop and old one.
^ permalink raw reply
* Re: [patch] sctp: cleanup: remove unneeded null check
From: Vlad Yasevich @ 2010-04-23 14:28 UTC (permalink / raw)
To: Dan Carpenter
Cc: Sridhar Samudrala, David S. Miller, Wei Yongjun, Chris Dischino,
linux-sctp, netdev, kernel-janitors
In-Reply-To: <20100423115906.GE29093@bicker>
Dan Carpenter wrote:
> "chunk" can never be null here. We dereferenced it earlier in the
> function and also at the start of the function we passed it to
> sctp_pack_cookie() which dereferences it.
>
> This code has been around since the dawn of git history so if "chunk"
> were ever null someone would have complained about it.
>
> Signed-off-by: Dan Carpenter <error27@gmail.com>
>
> diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
> index 17cb400..52352fc 100644
> --- a/net/sctp/sm_make_chunk.c
> +++ b/net/sctp/sm_make_chunk.c
> @@ -470,8 +470,7 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
> *
> * [INIT ACK back to where the INIT came from.]
> */
> - if (chunk)
> - retval->transport = chunk->transport;
> + retval->transport = chunk->transport;
>
Actually, this code can be completely removed as we already make this assignment
earlier:
/* Per the advice in RFC 2960 6.4, send this reply to
* the source of the INIT packet.
*/
retval->transport = chunk->transport;
retval->subh.init_hdr =
sctp_addto_chunk(retval, sizeof(initack), &initack);
-vlad
> nomem_chunk:
> kfree(cookie);
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Checkpoint and Restart of INET routing information
From: Dan Smith @ 2010-04-23 14:55 UTC (permalink / raw)
To: containers-qjLDD68F18O7TbgM5vRIOg; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA
This set extends the existing network socket, device, and namespace support
in the checkpoint tree to cover routing information. It does so by making
heavy use of RTNETLINK to dump and insert routes much like userspace would.
Because the task doing the checkpointing or restarting needs to examine
or setup resources for tasks in network namespaces other than its own, an
additional kernel socket setup call is added. It provides us the ability
to talk to RTNETLINK in a foreign netns.
The support added in this set allows me to configure various inet4 and inet6
routes in a container and have them saved and restored successfully during
a checkpoint/restart process.
^ permalink raw reply
* [PATCH 1/4] Fix acquiring socket lock before reading RTNETLINK response
From: Dan Smith @ 2010-04-23 14:55 UTC (permalink / raw)
To: containers-qjLDD68F18O7TbgM5vRIOg; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1272034539-19899-1-git-send-email-danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
Signed-off-by: Dan Smith <danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
net/checkpoint_dev.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/checkpoint_dev.c b/net/checkpoint_dev.c
index 7ccb899..2787892 100644
--- a/net/checkpoint_dev.c
+++ b/net/checkpoint_dev.c
@@ -136,11 +136,12 @@ static struct nlmsghdr *rtnl_get_response(struct socket *rtnl,
*skb = NULL;
+ lock_sock(rtnl->sk);
ret = sk_wait_data(rtnl->sk, &timeo);
- if (!ret)
- return ERR_PTR(-EPIPE);
+ if (ret)
+ *skb = skb_dequeue(&rtnl->sk->sk_receive_queue);
+ release_sock(rtnl->sk);
- *skb = skb_dequeue(&rtnl->sk->sk_receive_queue);
if (!*skb)
return ERR_PTR(-EPIPE);
--
1.6.2.5
^ permalink raw reply related
* [PATCH 2/4] [RFC] Add sock_create_kern_net()
From: Dan Smith @ 2010-04-23 14:55 UTC (permalink / raw)
To: containers-qjLDD68F18O7TbgM5vRIOg; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1272034539-19899-1-git-send-email-danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
This helper allows kernel routines to create a socket in a given netns,
instead of forcing it to the initial or current one.
I know this seems like it's violating the netns boundary. The intended
use (as in the following patches) is specifically when talking to RTNETLINK
in another netns for the purposes of creating or examining resources there.
It is expected that this will be used for that sort of transient socket
creation only. In other words:
s = sock_create_kern_net(AF_NETLINK, ..., other_netns, ...);
rtnl_talk(s);
close(s);
If this is acceptable, I will actually be able to clean up and simplify
other bits of the net checkpoint code to make better use of RTNL for
examining and restoring resources.
Perhaps we should assert that family == AF_NETLINK (or maybe just
printk(KERN_WARN) if it is not) to prevent abuse of this call?
Signed-off-by: Dan Smith <danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
include/linux/net.h | 2 ++
net/socket.c | 6 ++++++
2 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/include/linux/net.h b/include/linux/net.h
index 9548e45..9cfc899 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -235,6 +235,8 @@ extern int sock_create(int family, int type, int proto,
struct socket **res);
extern int sock_create_kern(int family, int type, int proto,
struct socket **res);
+extern int sock_create_kern_net(int family, int type, int protocol,
+ struct net *net, struct socket **res);
extern int sock_create_lite(int family, int type, int proto,
struct socket **res);
extern void sock_release(struct socket *sock);
diff --git a/net/socket.c b/net/socket.c
index 3253c04..95c94a7 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1294,6 +1294,12 @@ int sock_create_kern(int family, int type, int protocol, struct socket **res)
return __sock_create(&init_net, family, type, protocol, res, 1);
}
+int sock_create_kern_net(int family, int type, int protocol,
+ struct net *net, struct socket **res)
+{
+ return __sock_create(net, family, type, protocol, res, 1);
+}
+
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
int retval;
--
1.6.2.5
^ permalink raw reply related
* [PATCH 3/4] C/R: Make rtnl_open() and rtnl_do() take and pass a netns pointer
From: Dan Smith @ 2010-04-23 14:55 UTC (permalink / raw)
To: containers-qjLDD68F18O7TbgM5vRIOg; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1272034539-19899-1-git-send-email-danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
(also make rtnl_do() return negative or 0, not the message length)
Signed-off-by: Dan Smith <danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
net/checkpoint_dev.c | 16 +++++++++-------
1 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/net/checkpoint_dev.c b/net/checkpoint_dev.c
index 2787892..df8b16a 100644
--- a/net/checkpoint_dev.c
+++ b/net/checkpoint_dev.c
@@ -107,12 +107,13 @@ static int __kern_dev_ioctl(struct net *net, unsigned int cmd, void *arg)
return ret;
}
-static struct socket *rtnl_open(void)
+static struct socket *rtnl_open(struct net *net)
{
struct socket *sock;
int ret;
- ret = sock_create(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE, &sock);
+ ret = sock_create_kern_net(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE,
+ net, &sock);
if (ret < 0)
return ERR_PTR(ret);
@@ -538,7 +539,7 @@ static struct sk_buff *del_link_msg(char *name)
return skb;
}
-static int rtnl_do(struct sk_buff *skb)
+static int rtnl_do(struct net *net, struct sk_buff *skb)
{
int ret = -ENOMEM;
struct socket *rtnl = NULL;
@@ -551,7 +552,7 @@ static int rtnl_do(struct sk_buff *skb)
kvec.iov_len = skb->len;
kvec.iov_base = skb->head;
- rtnl = rtnl_open();
+ rtnl = rtnl_open(net);
if (IS_ERR(rtnl)) {
ret = PTR_ERR(rtnl);
ckpt_debug("Unable to open rtnetlink socket: %i\n", ret);
@@ -570,7 +571,8 @@ static int rtnl_do(struct sk_buff *skb)
if (IS_ERR(nlh)) {
ret = PTR_ERR(nlh);
ckpt_debug("RTNETLINK said: %i\n", ret);
- }
+ } else
+ ret = 0;
out:
rtnl_close(rtnl);
kfree_skb(rskb);
@@ -590,7 +592,7 @@ static struct net_device *rtnl_newlink(new_link_fn fn, void *data, char *name)
return ERR_PTR(PTR_ERR(skb));
}
- ret = rtnl_do(skb);
+ ret = rtnl_do(current->nsproxy->net_ns, skb);
kfree_skb(skb);
if (ret < 0)
return ERR_PTR(ret);
@@ -610,7 +612,7 @@ static int rtnl_dellink(char *name)
return PTR_ERR(skb);
}
- ret = rtnl_do(skb);
+ ret = rtnl_do(current->nsproxy->net_ns, skb);
kfree_skb(skb);
return ret;
--
1.6.2.5
^ permalink raw reply related
* [PATCH 4/4] C/R: inet4 and inet6 unicast routes
From: Dan Smith @ 2010-04-23 14:55 UTC (permalink / raw)
To: containers-qjLDD68F18O7TbgM5vRIOg; +Cc: netdev-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1272034539-19899-1-git-send-email-danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
This patch adds support for checkpointing and restoring route information.
It keeps enough information to restore basic routes at the level of detail
of /proc/net/route. It uses RTNETLINK to extract the information during
checkpoint and also to insert it back during restore. This gives us a
nice layer of isolation between us and the various "fib" implementations.
Signed-off-by: Dan Smith <danms-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
---
include/linux/checkpoint_hdr.h | 31 +++
net/checkpoint_dev.c | 412 +++++++++++++++++++++++++++++++++++++++-
2 files changed, 442 insertions(+), 1 deletions(-)
diff --git a/include/linux/checkpoint_hdr.h b/include/linux/checkpoint_hdr.h
index 633c9b0..187d706 100644
--- a/include/linux/checkpoint_hdr.h
+++ b/include/linux/checkpoint_hdr.h
@@ -23,6 +23,7 @@
#include <sys/un.h>
#include <netinet/in.h>
#endif
+#include <linux/if.h>
/*
* /usr/include/linux/security.h is not exported to userspace, so
@@ -783,6 +784,7 @@ struct ckpt_hdr_file_socket {
struct ckpt_hdr_netns {
struct ckpt_hdr h;
__s32 this_ref;
+ __u32 routes;
} __attribute__((aligned(8)));
enum ckpt_netdev_types {
@@ -837,6 +839,35 @@ struct ckpt_netdev_addr {
} __attribute__((aligned(8)));
} __attribute__((aligned(8)));
+enum ckpt_route_types {
+ CKPT_ROUTE_IPV4,
+ CKPT_ROUTE_IPV6,
+ CKPT_ROUTE_MAX
+};
+
+#define CKPT_ROUTE_FLAG_GW 1
+
+struct ckpt_route {
+ __u16 type;
+ __u16 flags;
+
+ union {
+ struct {
+ __be32 inet4_len; /* mask length (bits) */
+ __u32 inet4_met; /* metric */
+ __be32 inet4_dst; /* route address */
+ __be32 inet4_gwy; /* gateway address */
+ };
+ struct {
+ __u32 inet6_len; /* mask length (bits) */
+ __u32 inet6_met; /* metric */
+ struct in6_addr inet6_dst; /* route address */
+ struct in6_addr inet6_gwy; /* gateway address */
+ };
+ } __attribute__((aligned(8)));
+ char dev[IFNAMSIZ+1];
+} __attribute__((aligned(8)));
+
struct ckpt_hdr_eventpoll_items {
struct ckpt_hdr h;
__s32 epfile_objref;
diff --git a/net/checkpoint_dev.c b/net/checkpoint_dev.c
index df8b16a..b34d1f2 100644
--- a/net/checkpoint_dev.c
+++ b/net/checkpoint_dev.c
@@ -17,9 +17,11 @@
#include <linux/checkpoint_hdr.h>
#include <linux/deferqueue.h>
#include <linux/module.h>
+#include <linux/fib_rules.h>
#include <net/net_namespace.h>
#include <net/sch_generic.h>
+#include <net/ipv6.h>
struct veth_newlink {
char *peer;
@@ -107,6 +109,22 @@ static int __kern_dev_ioctl(struct net *net, unsigned int cmd, void *arg)
return ret;
}
+static void debug_route(struct ckpt_route *route)
+{
+ if (route->type == CKPT_ROUTE_IPV4)
+ ckpt_debug("inet4 route %pI4/%i gw %pI4 metric %i dev %s\n",
+ &route->inet4_dst, route->inet4_len,
+ &route->inet4_gwy, route->inet4_met,
+ route->dev);
+ else if (route->type == CKPT_ROUTE_IPV6)
+ ckpt_debug("inet6 route %pI6/%i gw %pI6 metric %i dev %s\n",
+ &route->inet6_dst, route->inet6_len,
+ &route->inet6_gwy, route->inet6_met,
+ route->dev);
+ else
+ ckpt_debug("unknown route type %i\n", route->type);
+}
+
static struct socket *rtnl_open(struct net *net)
{
struct socket *sock;
@@ -313,11 +331,236 @@ int checkpoint_netdev(struct ckpt_ctx *ctx, void *ptr)
return ret;
}
+static int rtnl_dump_routes(struct socket *rtnl, int family)
+{
+ struct sk_buff *skb;
+ struct rtmsg *rtm;
+ int flags = NLM_F_ROOT | NLM_F_REQUEST;
+ struct msghdr msg;
+ struct kvec kvec;
+ struct nlmsghdr *nlh;
+ int ret = -ENOMEM;
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ nlh = nlmsg_put(skb, 0, 0, RTM_GETROUTE, sizeof(*rtm), flags);
+ if (!nlh)
+ goto out;
+
+ rtm = nlmsg_data(nlh);
+ memset(rtm, 0, sizeof(*rtm));
+ rtm->rtm_family = family;
+
+ nlmsg_end(skb, nlh);
+
+ memset(&msg, 0, sizeof(msg));
+ kvec.iov_len = skb->len;
+ kvec.iov_base = skb->head;
+
+ ret = kernel_sendmsg(rtnl, &msg, &kvec, 1, kvec.iov_len);
+ if ((ret >= 0) && (ret != skb->len))
+ ret = -EIO;
+ out:
+ kfree_skb(skb);
+ return ret;
+}
+
+static int rtnl_process_inet4_route(struct net *net,
+ struct rtmsg *rtm,
+ struct nlattr **tb,
+ struct ckpt_route *route)
+{
+ if (rtm->rtm_type != RTN_UNICAST)
+ return 0; /* skip non-unicast routes */
+
+ route->type = CKPT_ROUTE_IPV4;
+ route->inet4_len = rtm->rtm_dst_len;
+
+ if (tb[RTA_DST])
+ route->inet4_dst = htonl(nla_get_u32(tb[RTA_DST]));
+ if (tb[RTA_GATEWAY]) {
+ route->flags |= CKPT_ROUTE_FLAG_GW;
+ route->inet4_gwy = htonl(nla_get_u32(tb[RTA_GATEWAY]));
+ }
+ if (tb[RTA_PRIORITY])
+ route->inet4_met = nla_get_u32(tb[RTA_PRIORITY]);
+
+ if (tb[RTA_OIF]) {
+ struct net_device *dev;
+
+ dev = dev_get_by_index(net, nla_get_u32(tb[RTA_OIF]));
+ if (dev) {
+ strncpy(route->dev, dev->name, IFNAMSIZ);
+ dev_put(dev);
+ }
+ }
+
+ debug_route(route);
+
+ return 1; /* save this route */
+}
+
+static int rtnl_process_inet6_route(struct net *net,
+ struct rtmsg *rtm,
+ struct nlattr **tb,
+ struct ckpt_route *route)
+{
+ if (rtm->rtm_type != RTN_UNICAST)
+ return 0; /* skip non-unicast routes */
+
+ route->type = CKPT_ROUTE_IPV6;
+ route->inet6_len = rtm->rtm_dst_len;
+
+ if (tb[RTA_DST])
+ ipv6_addr_copy(&route->inet6_dst, nla_data(tb[RTA_DST]));
+ if (tb[RTA_GATEWAY]) {
+ route->flags |= CKPT_ROUTE_FLAG_GW;
+ ipv6_addr_copy(&route->inet6_gwy, nla_data(tb[RTA_GATEWAY]));
+ }
+ if (tb[RTA_PRIORITY])
+ route->inet6_met = nla_get_u32(tb[RTA_PRIORITY]);
+
+ if (tb[RTA_OIF]) {
+ struct net_device *dev;
+
+ dev = dev_get_by_index(net, nla_get_u32(tb[RTA_OIF]));
+ if (dev) {
+ strncpy(route->dev, dev->name, IFNAMSIZ);
+ dev_put(dev);
+ }
+ }
+
+ debug_route(route);
+
+ return 1;
+}
+
+static int rtnl_process_routes(struct net *net,
+ struct nlmsghdr *nlh, int len,
+ struct ckpt_route *routes,
+ int idx, int max)
+{
+ struct nlmsghdr *i;
+
+ for (i = nlh; NLMSG_OK(i, len); i = NLMSG_NEXT(i, len)) {
+ struct ckpt_route *route = &routes[idx];
+ struct rtmsg *rtm = NLMSG_DATA(i);
+ struct nlattr *tb[FRA_MAX+1];
+ int ret;
+
+ if (idx >= max)
+ return -E2BIG;
+
+ if (i->nlmsg_type == NLMSG_DONE)
+ break;
+ else if (nlh->nlmsg_type != RTM_NEWROUTE) {
+ struct nlmsgerr *errmsg = nlmsg_data(nlh);
+ return errmsg->error;
+ }
+
+ ret = nlmsg_parse(i, sizeof(*rtm), tb, FRA_MAX, NULL);
+ if (ret < 0)
+ return ret;
+
+ memset(route, 0, sizeof(*route));
+
+ if (rtm->rtm_family == AF_INET)
+ ret = rtnl_process_inet4_route(net, rtm, tb, route);
+ else if (rtm->rtm_family == AF_INET6)
+ ret = rtnl_process_inet6_route(net, rtm, tb, route);
+ else
+ ret = 0; /* skip */
+ if (ret < 0)
+ return ret;
+ else if (ret)
+ idx += 1;
+ }
+
+ return idx;
+}
+
+static int rtnl_get_routes(struct net *net, int family,
+ struct ckpt_route *routes, int idx, int max)
+{
+ int ret;
+ long timeo = MAX_SCHEDULE_TIMEOUT;
+ struct nlmsghdr *nlh;
+ struct sk_buff *skb = NULL;
+ struct socket *rtnl = NULL;
+
+ rtnl = rtnl_open(net);
+ if (IS_ERR(rtnl))
+ return PTR_ERR(rtnl);
+
+ ret = rtnl_dump_routes(rtnl, family);
+ if (ret < 0)
+ goto out;
+
+ lock_sock(rtnl->sk);
+ ret = sk_wait_data(rtnl->sk, &timeo);
+ if (ret)
+ skb = skb_dequeue(&rtnl->sk->sk_receive_queue);
+ release_sock(rtnl->sk);
+ if (!skb) {
+ ret = -EIO;
+ goto out;
+ }
+
+ nlh = nlmsg_hdr(skb);
+ if (!nlh) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = rtnl_process_routes(net, nlh, skb->len, routes, idx, max);
+ out:
+ rtnl_close(rtnl);
+ kfree_skb(skb);
+ return ret;
+}
+
+int checkpoint_netns_routes(struct ckpt_ctx *ctx, struct net *net,
+ struct ckpt_route **_routes)
+{
+ struct ckpt_route *routes = NULL;
+ int max = 32;
+ int idx;
+ int families[] = {AF_INET, AF_INET6, 0};
+ int family;
+ retry:
+ idx = 0;
+ kfree(routes);
+ routes = kmalloc(max * sizeof(*routes), GFP_KERNEL);
+ if (!routes)
+ return -ENOMEM;
+
+ for (family = 0; families[family]; family++) {
+ idx = rtnl_get_routes(net, families[family], routes, idx, max);
+ if (idx == -E2BIG) {
+ max *= 2;
+ goto retry;
+ } else if (idx < 0)
+ break;
+ }
+
+ if (idx < 0) {
+ kfree(routes);
+ routes = NULL;
+ ckpt_err(ctx, idx, "error saving routes\n");
+ }
+ *_routes = routes;
+
+ return idx;
+}
+
int checkpoint_netns(struct ckpt_ctx *ctx, void *ptr)
{
struct net *net = ptr;
struct net_device *dev;
struct ckpt_hdr_netns *h;
+ struct ckpt_route *routes = NULL;
int ret;
h = ckpt_hdr_get_type(ctx, sizeof(*h), CKPT_HDR_NET_NS);
@@ -327,10 +570,19 @@ int checkpoint_netns(struct ckpt_ctx *ctx, void *ptr)
h->this_ref = ckpt_obj_lookup(ctx, net, CKPT_OBJ_NET_NS);
BUG_ON(h->this_ref <= 0);
+ ret = checkpoint_netns_routes(ctx, net, &routes);
+ if (ret < 0)
+ goto out;
+ h->routes = ret;
+
ret = ckpt_write_obj(ctx, (struct ckpt_hdr *) h);
if (ret < 0)
goto out;
+ ret = ckpt_write_buffer(ctx, routes, h->routes * sizeof(*routes));
+ if (ret < 0)
+ goto out;
+
for_each_netdev(net, dev) {
if (dev->netdev_ops->ndo_checkpoint)
ret = checkpoint_obj(ctx, dev, CKPT_OBJ_NETDEV);
@@ -347,6 +599,7 @@ int checkpoint_netns(struct ckpt_ctx *ctx, void *ptr)
}
out:
ckpt_hdr_put(ctx, h);
+ kfree(routes);
return ret;
}
@@ -862,10 +1115,145 @@ void *restore_netdev(struct ckpt_ctx *ctx)
return dev;
}
+static int rtnl_restore_route(struct net *net, struct ckpt_route *route)
+{
+ struct sk_buff *skb;
+ struct rtmsg *rtm;
+ int flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK;
+ struct nlmsghdr *nlh;
+ int ret = 0;
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!skb)
+ return -ENOMEM;
+
+ nlh = nlmsg_put(skb, 0, 0, RTM_NEWROUTE, sizeof(*rtm), flags);
+ if (!nlh) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ rtm = nlmsg_data(nlh);
+ memset(rtm, 0, sizeof(*rtm));
+
+ rtm->rtm_table = RT_TABLE_MAIN;
+ rtm->rtm_protocol = RTPROT_BOOT;
+ rtm->rtm_scope = RT_SCOPE_UNIVERSE;
+ rtm->rtm_type = RTN_UNICAST;
+
+ if (route->dev[0]) {
+ struct net_device *dev;
+
+ dev = dev_get_by_name(net, route->dev);
+ if (!dev) {
+ ckpt_debug("unable to find dev %s for route\n",
+ route->dev);
+ ret = -EINVAL;
+ goto out;
+ }
+ nla_put_u32(skb, RTA_OIF, dev->ifindex);
+ dev_put(dev);
+ }
+
+ if (route->type == CKPT_ROUTE_IPV4) {
+ rtm->rtm_family = AF_INET;
+ rtm->rtm_dst_len = route->inet4_len;
+
+ nla_put_u32(skb, RTA_DST, route->inet4_dst);
+ if (route->flags & CKPT_ROUTE_FLAG_GW)
+ nla_put_u32(skb, RTA_GATEWAY, route->inet4_gwy);
+ nla_put_u32(skb, RTA_PRIORITY, route->inet4_met);
+ } else if (route->type == CKPT_ROUTE_IPV6) {
+ int len = sizeof(route->inet6_dst);
+
+ if (ipv6_addr_scope(&route->inet6_dst))
+ goto out; /* Skip non-global scope routes */
+
+ rtm->rtm_family = AF_INET6;
+ rtm->rtm_dst_len = route->inet6_len;
+
+ nla_put(skb, RTA_DST, len, &route->inet6_dst);
+ if (route->flags & CKPT_ROUTE_FLAG_GW)
+ nla_put(skb, RTA_GATEWAY, len, &route->inet6_gwy);
+ nla_put_u32(skb, RTA_PRIORITY, route->inet6_met);
+ } else {
+ ckpt_debug("unsupported route type %i\n", route->type);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ nlmsg_end(skb, nlh);
+
+ debug_route(route);
+
+ ret = rtnl_do(net, skb);
+ out:
+ kfree_skb(skb);
+ return ret;
+}
+
+static int restore_routes(struct net *net, struct ckpt_route *routes, int count)
+{
+ int i;
+ int ret = 0;
+
+ for (i = 0; i < count; i++) {
+ struct ckpt_route *route = &routes[i];
+
+ ret = rtnl_restore_route(net, route);
+ if (ret == -EEXIST)
+ /* Some routes have been implied by device addresses */
+ continue;
+ else if (ret < 0)
+ break;
+ }
+
+ return ret;
+}
+
+struct dq_routes {
+ struct ckpt_ctx *ctx;
+ struct net *net;
+ struct ckpt_route *routes;
+ int count;
+};
+
+static int deferred_restore_routes(void *data)
+{
+ struct dq_routes *dq = data;
+ int ret;
+
+ ret = restore_routes(dq->net, dq->routes, dq->count);
+ if (ret < 0)
+ ckpt_err(dq->ctx, ret, "failed to restore routes\n");
+
+ kfree(dq->routes);
+
+ return ret;
+}
+
+static int defer_restore_routes(struct ckpt_ctx *ctx,
+ struct net *net,
+ struct ckpt_route *routes,
+ int count)
+{
+ struct dq_routes dq;
+
+ dq.ctx = ctx;
+ dq.net = net;
+ dq.routes = routes;
+ dq.count = count;
+
+ return deferqueue_add(ctx->files_deferq, &dq, sizeof(dq),
+ deferred_restore_routes, NULL);
+}
+
void *restore_netns(struct ckpt_ctx *ctx)
{
struct ckpt_hdr_netns *h;
struct net *net;
+ struct ckpt_route *routes = NULL;
+ int ret;
h = ckpt_read_obj_type(ctx, sizeof(*h), CKPT_HDR_NET_NS);
if (IS_ERR(h)) {
@@ -873,12 +1261,34 @@ void *restore_netns(struct ckpt_ctx *ctx)
return h;
}
+ ret = ckpt_read_payload(ctx, (void **)&routes,
+ h->routes * sizeof(*routes), CKPT_HDR_BUFFER);
+ if (ret < 0) {
+ ckpt_err(ctx, ret, "Unable to read routes buffer\n");
+ net = ERR_PTR(ret);
+ goto out;
+ }
+
if (h->this_ref != 0) {
net = copy_net_ns(CLONE_NEWNET, current->nsproxy->net_ns);
if (IS_ERR(net))
goto out;
- } else
+
+ ret = defer_restore_routes(ctx, net, routes, h->routes);
+ if (ret < 0) {
+ kfree(routes);
+ put_net(net);
+ net = ERR_PTR(ret);
+ }
+ } else {
+ if (h->routes) {
+ net = ERR_PTR(-EINVAL);
+ ckpt_err(ctx, -EINVAL,
+ "Parent netns claims to have routes\n");
+ goto out;
+ }
net = current->nsproxy->net_ns;
+ }
out:
ckpt_hdr_put(ctx, h);
--
1.6.2.5
^ permalink raw reply related
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