/* niu.c: Neptune ethernet driver.
*
- * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net)
*/
#include <linux/module.h>
#define DRV_MODULE_NAME "niu"
#define PFX DRV_MODULE_NAME ": "
-#define DRV_MODULE_VERSION "0.7"
-#define DRV_MODULE_RELDATE "February 18, 2008"
+#define DRV_MODULE_VERSION "0.9"
+#define DRV_MODULE_RELDATE "May 4, 2008"
static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
}
if ((sig & mask) != val) {
+ if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
+ np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+ return 0;
+ }
dev_err(np->device, PFX "Port %u signal bits [%08x] are not "
"[%08x]\n", np->port, (int) (sig & mask), (int) val);
return -ENODEV;
}
-
+ if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
+ np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
return 0;
}
return 0;
}
-
static int link_status_10g_serdes(struct niu *np, int *link_up_p)
{
unsigned long flags;
return 0;
}
-
static int link_status_1g_rgmii(struct niu *np, int *link_up_p)
{
struct niu_link_config *lp = &np->link_config;
return err;
}
-
static int bcm8704_reset(struct niu *np)
{
int err, limit;
return 0;
}
+static int bcm8706_init_user_dev3(struct niu *np)
+{
+ int err;
+
+
+ err = mdio_read(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_OPT_DIGITAL_CTRL);
+ if (err < 0)
+ return err;
+ err &= ~USER_ODIG_CTRL_GPIOS;
+ err |= (0x3 << USER_ODIG_CTRL_GPIOS_SHIFT);
+ err |= USER_ODIG_CTRL_RESV2;
+ err = mdio_write(np, np->phy_addr, BCM8704_USER_DEV3_ADDR,
+ BCM8704_USER_OPT_DIGITAL_CTRL, err);
+ if (err)
+ return err;
+
+ mdelay(1000);
+
+ return 0;
+}
+
static int bcm8704_init_user_dev3(struct niu *np)
{
int err;
MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX);
}
-static int xcvr_init_10g_bcm8704(struct niu *np)
+
+static int xcvr_diag_bcm870x(struct niu *np)
{
- struct niu_link_config *lp = &np->link_config;
u16 analog_stat0, tx_alarm_status;
- int err;
-
- err = bcm8704_reset(np);
- if (err)
- return err;
-
- err = bcm8704_init_user_dev3(np);
- if (err)
- return err;
-
- err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
- MII_BMCR);
- if (err < 0)
- return err;
- err &= ~BMCR_LOOPBACK;
-
- if (lp->loopback_mode == LOOPBACK_MAC)
- err |= BMCR_LOOPBACK;
-
- err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
- MII_BMCR, err);
- if (err)
- return err;
+ int err = 0;
#if 1
err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
return 0;
}
+static int xcvr_10g_set_lb_bcm870x(struct niu *np)
+{
+ struct niu_link_config *lp = &np->link_config;
+ int err;
+
+ err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+ MII_BMCR);
+ if (err < 0)
+ return err;
+
+ err &= ~BMCR_LOOPBACK;
+
+ if (lp->loopback_mode == LOOPBACK_MAC)
+ err |= BMCR_LOOPBACK;
+
+ err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+ MII_BMCR, err);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int xcvr_init_10g_bcm8706(struct niu *np)
+{
+ int err = 0;
+ u64 val;
+
+ if ((np->flags & NIU_FLAGS_HOTPLUG_PHY) &&
+ (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) == 0)
+ return err;
+
+ val = nr64_mac(XMAC_CONFIG);
+ val &= ~XMAC_CONFIG_LED_POLARITY;
+ val |= XMAC_CONFIG_FORCE_LED_ON;
+ nw64_mac(XMAC_CONFIG, val);
+
+ val = nr64(MIF_CONFIG);
+ val |= MIF_CONFIG_INDIRECT_MODE;
+ nw64(MIF_CONFIG, val);
+
+ err = bcm8704_reset(np);
+ if (err)
+ return err;
+
+ err = xcvr_10g_set_lb_bcm870x(np);
+ if (err)
+ return err;
+
+ err = bcm8706_init_user_dev3(np);
+ if (err)
+ return err;
+
+ err = xcvr_diag_bcm870x(np);
+ if (err)
+ return err;
+
+ return 0;
+}
+
+static int xcvr_init_10g_bcm8704(struct niu *np)
+{
+ int err;
+
+ err = bcm8704_reset(np);
+ if (err)
+ return err;
+
+ err = bcm8704_init_user_dev3(np);
+ if (err)
+ return err;
+
+ err = xcvr_10g_set_lb_bcm870x(np);
+ if (err)
+ return err;
+
+ err = xcvr_diag_bcm870x(np);
+ if (err)
+ return err;
+
+ return 0;
+}
+
static int xcvr_init_10g(struct niu *np)
{
int phy_id, err;
return 0;
}
-
-
static int xcvr_init_1g_rgmii(struct niu *np)
{
int err;
return 0;
}
-
static int mii_init_common(struct niu *np)
{
struct niu_link_config *lp = &np->link_config;
return err;
}
+static int link_status_10g_bcm8706(struct niu *np, int *link_up_p)
+{
+ int err, link_up;
+ link_up = 0;
+
+ err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR,
+ BCM8704_PMD_RCV_SIGDET);
+ if (err < 0)
+ goto out;
+ if (!(err & PMD_RCV_SIGDET_GLOBAL)) {
+ err = 0;
+ goto out;
+ }
+
+ err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR,
+ BCM8704_PCS_10G_R_STATUS);
+ if (err < 0)
+ goto out;
+
+ if (!(err & PCS_10G_R_STATUS_BLK_LOCK)) {
+ err = 0;
+ goto out;
+ }
+
+ err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR,
+ BCM8704_PHYXS_XGXS_LANE_STAT);
+ if (err < 0)
+ goto out;
+ if (err != (PHYXS_XGXS_LANE_STAT_ALINGED |
+ PHYXS_XGXS_LANE_STAT_MAGIC |
+ PHYXS_XGXS_LANE_STAT_PATTEST |
+ PHYXS_XGXS_LANE_STAT_LANE3 |
+ PHYXS_XGXS_LANE_STAT_LANE2 |
+ PHYXS_XGXS_LANE_STAT_LANE1 |
+ PHYXS_XGXS_LANE_STAT_LANE0)) {
+ err = 0;
+ np->link_config.active_speed = SPEED_INVALID;
+ np->link_config.active_duplex = DUPLEX_INVALID;
+ goto out;
+ }
+
+ link_up = 1;
+ np->link_config.active_speed = SPEED_10000;
+ np->link_config.active_duplex = DUPLEX_FULL;
+ err = 0;
+
+out:
+ *link_up_p = link_up;
+ if (np->flags & NIU_FLAGS_HOTPLUG_PHY)
+ err = 0;
+ return err;
+}
+
static int link_status_10g_bcom(struct niu *np, int *link_up_p)
{
int err, link_up;
return err;
}
+static int niu_10g_phy_present(struct niu *np)
+{
+ u64 sig, mask, val;
+
+ sig = nr64(ESR_INT_SIGNALS);
+ switch (np->port) {
+ case 0:
+ mask = ESR_INT_SIGNALS_P0_BITS;
+ val = (ESR_INT_SRDY0_P0 |
+ ESR_INT_DET0_P0 |
+ ESR_INT_XSRDY_P0 |
+ ESR_INT_XDP_P0_CH3 |
+ ESR_INT_XDP_P0_CH2 |
+ ESR_INT_XDP_P0_CH1 |
+ ESR_INT_XDP_P0_CH0);
+ break;
+
+ case 1:
+ mask = ESR_INT_SIGNALS_P1_BITS;
+ val = (ESR_INT_SRDY0_P1 |
+ ESR_INT_DET0_P1 |
+ ESR_INT_XSRDY_P1 |
+ ESR_INT_XDP_P1_CH3 |
+ ESR_INT_XDP_P1_CH2 |
+ ESR_INT_XDP_P1_CH1 |
+ ESR_INT_XDP_P1_CH0);
+ break;
+
+ default:
+ return 0;
+ }
+
+ if ((sig & mask) != val)
+ return 0;
+ return 1;
+}
+
+static int link_status_10g_hotplug(struct niu *np, int *link_up_p)
+{
+ unsigned long flags;
+ int err = 0;
+ int phy_present;
+ int phy_present_prev;
+
+ spin_lock_irqsave(&np->lock, flags);
+
+ if (np->link_config.loopback_mode == LOOPBACK_DISABLED) {
+ phy_present_prev = (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) ?
+ 1 : 0;
+ phy_present = niu_10g_phy_present(np);
+ if (phy_present != phy_present_prev) {
+ /* state change */
+ if (phy_present) {
+ np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+ if (np->phy_ops->xcvr_init)
+ err = np->phy_ops->xcvr_init(np);
+ if (err) {
+ /* debounce */
+ np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+ }
+ } else {
+ np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT;
+ *link_up_p = 0;
+ niuwarn(LINK, "%s: Hotplug PHY Removed\n",
+ np->dev->name);
+ }
+ }
+ if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT)
+ err = link_status_10g_bcm8706(np, link_up_p);
+ }
+
+ spin_unlock_irqrestore(&np->lock, flags);
+
+ return err;
+}
+
static int link_status_1g(struct niu *np, int *link_up_p)
{
struct niu_link_config *lp = &np->link_config;
.link_status = link_status_10g,
};
+static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = {
+ .serdes_init = serdes_init_10g,
+ .xcvr_init = xcvr_init_10g_bcm8706,
+ .link_status = link_status_10g_hotplug,
+};
+
static const struct niu_phy_ops phy_ops_10g_copper = {
.serdes_init = serdes_init_10g,
.link_status = link_status_10g, /* XXX */
.phy_addr_base = 8,
};
+static const struct niu_phy_template phy_template_10g_fiber_hotplug = {
+ .ops = &phy_ops_10g_fiber_hotplug,
+ .phy_addr_base = 8,
+};
+
static const struct niu_phy_template phy_template_10g_copper = {
.ops = &phy_ops_10g_copper,
.phy_addr_base = 10,
plat_type == PLAT_TYPE_VF_P1)
phy_addr_off = 8;
phy_addr_off += np->port;
+ if (np->flags & NIU_FLAGS_HOTPLUG_PHY) {
+ tp = &phy_template_10g_fiber_hotplug;
+ if (np->port == 0)
+ phy_addr_off = 8;
+ if (np->port == 1)
+ phy_addr_off = 12;
+ }
break;
case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES:
static void niu_tx_work(struct niu *np, struct tx_ring_info *rp)
{
+ struct netdev_queue *txq;
u16 pkt_cnt, tmp;
- int cons;
+ int cons, index;
u64 cs;
+ index = (rp - np->tx_rings);
+ txq = netdev_get_tx_queue(np->dev, index);
+
cs = rp->tx_cs;
if (unlikely(!(cs & (TX_CS_MK | TX_CS_MMK))))
goto out;
smp_mb();
out:
- if (unlikely(netif_queue_stopped(np->dev) &&
+ if (unlikely(netif_tx_queue_stopped(txq) &&
(niu_tx_avail(rp) > NIU_TX_WAKEUP_THRESH(rp)))) {
- netif_tx_lock(np->dev);
- if (netif_queue_stopped(np->dev) &&
+ __netif_tx_lock(txq, smp_processor_id());
+ if (netif_tx_queue_stopped(txq) &&
(niu_tx_avail(rp) > NIU_TX_WAKEUP_THRESH(rp)))
- netif_wake_queue(np->dev);
- netif_tx_unlock(np->dev);
+ netif_tx_wake_queue(txq);
+ __netif_tx_unlock(txq);
}
}
np->num_rx_rings = parent->rxchan_per_port[port];
np->num_tx_rings = parent->txchan_per_port[port];
+ np->dev->real_num_tx_queues = np->num_tx_rings;
+
np->rx_rings = kzalloc(np->num_rx_rings * sizeof(struct rx_ring_info),
GFP_KERNEL);
err = -ENOMEM;
goto out_free_irq;
}
- netif_start_queue(dev);
+ netif_tx_start_all_queues(dev);
if (np->link_config.loopback_mode != LOOPBACK_DISABLED)
netif_carrier_on(dev);
cancel_work_sync(&np->reset_task);
niu_disable_napi(np);
- netif_stop_queue(dev);
+ netif_tx_stop_all_queues(dev);
del_timer_sync(&np->timer);
* so long as all callers are assured to have free tx slots
* (such as after niu_init_hw).
*/
- netif_wake_queue(np->dev);
+ netif_tx_wake_all_queues(np->dev);
niu_enable_napi(np);
return ret;
}
-static struct tx_ring_info *tx_ring_select(struct niu *np, struct sk_buff *skb)
-{
- return &np->tx_rings[0];
-}
-
static int niu_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct niu *np = netdev_priv(dev);
unsigned long align, headroom;
+ struct netdev_queue *txq;
struct tx_ring_info *rp;
struct tx_pkt_hdr *tp;
unsigned int len, nfg;
int prod, i, tlen;
u64 mapping, mrk;
- rp = tx_ring_select(np, skb);
+ i = skb_get_queue_mapping(skb);
+ rp = &np->tx_rings[i];
+ txq = netdev_get_tx_queue(dev, i);
if (niu_tx_avail(rp) <= (skb_shinfo(skb)->nr_frags + 1)) {
- netif_stop_queue(dev);
+ netif_tx_stop_queue(txq);
dev_err(np->device, PFX "%s: BUG! Tx ring full when "
"queue awake!\n", dev->name);
rp->tx_errors++;
nw64(TX_RING_KICK(rp->tx_channel), rp->wrap_bit | (prod << 3));
if (unlikely(niu_tx_avail(rp) <= (MAX_SKB_FRAGS + 1))) {
- netif_stop_queue(dev);
+ netif_tx_stop_queue(txq);
if (niu_tx_avail(rp) > NIU_TX_WAKEUP_THRESH(rp))
- netif_wake_queue(dev);
+ netif_tx_wake_queue(txq);
}
dev->trans_start = jiffies;
spin_unlock_irq(&np->lock);
if (!err) {
- netif_start_queue(dev);
+ netif_tx_start_all_queues(dev);
if (np->link_config.loopback_mode != LOOPBACK_DISABLED)
netif_carrier_on(dev);
return 0;
}
+static int niu_ethflow_to_class(int flow_type, u64 *class)
+{
+ switch (flow_type) {
+ case TCP_V4_FLOW:
+ *class = CLASS_CODE_TCP_IPV4;
+ break;
+ case UDP_V4_FLOW:
+ *class = CLASS_CODE_UDP_IPV4;
+ break;
+ case AH_ESP_V4_FLOW:
+ *class = CLASS_CODE_AH_ESP_IPV4;
+ break;
+ case SCTP_V4_FLOW:
+ *class = CLASS_CODE_SCTP_IPV4;
+ break;
+ case TCP_V6_FLOW:
+ *class = CLASS_CODE_TCP_IPV6;
+ break;
+ case UDP_V6_FLOW:
+ *class = CLASS_CODE_UDP_IPV6;
+ break;
+ case AH_ESP_V6_FLOW:
+ *class = CLASS_CODE_AH_ESP_IPV6;
+ break;
+ case SCTP_V6_FLOW:
+ *class = CLASS_CODE_SCTP_IPV6;
+ break;
+ default:
+ return -1;
+ }
+
+ return 1;
+}
+
+static u64 niu_flowkey_to_ethflow(u64 flow_key)
+{
+ u64 ethflow = 0;
+
+ if (flow_key & FLOW_KEY_PORT)
+ ethflow |= RXH_DEV_PORT;
+ if (flow_key & FLOW_KEY_L2DA)
+ ethflow |= RXH_L2DA;
+ if (flow_key & FLOW_KEY_VLAN)
+ ethflow |= RXH_VLAN;
+ if (flow_key & FLOW_KEY_IPSA)
+ ethflow |= RXH_IP_SRC;
+ if (flow_key & FLOW_KEY_IPDA)
+ ethflow |= RXH_IP_DST;
+ if (flow_key & FLOW_KEY_PROTO)
+ ethflow |= RXH_L3_PROTO;
+ if (flow_key & (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_0_SHIFT))
+ ethflow |= RXH_L4_B_0_1;
+ if (flow_key & (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_1_SHIFT))
+ ethflow |= RXH_L4_B_2_3;
+
+ return ethflow;
+
+}
+
+static int niu_ethflow_to_flowkey(u64 ethflow, u64 *flow_key)
+{
+ u64 key = 0;
+
+ if (ethflow & RXH_DEV_PORT)
+ key |= FLOW_KEY_PORT;
+ if (ethflow & RXH_L2DA)
+ key |= FLOW_KEY_L2DA;
+ if (ethflow & RXH_VLAN)
+ key |= FLOW_KEY_VLAN;
+ if (ethflow & RXH_IP_SRC)
+ key |= FLOW_KEY_IPSA;
+ if (ethflow & RXH_IP_DST)
+ key |= FLOW_KEY_IPDA;
+ if (ethflow & RXH_L3_PROTO)
+ key |= FLOW_KEY_PROTO;
+ if (ethflow & RXH_L4_B_0_1)
+ key |= (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_0_SHIFT);
+ if (ethflow & RXH_L4_B_2_3)
+ key |= (FLOW_KEY_L4_BYTE12 << FLOW_KEY_L4_1_SHIFT);
+
+ *flow_key = key;
+
+ return 1;
+
+}
+
+static int niu_get_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+ struct niu *np = netdev_priv(dev);
+ u64 class;
+
+ cmd->data = 0;
+
+ if (!niu_ethflow_to_class(cmd->flow_type, &class))
+ return -EINVAL;
+
+ if (np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] &
+ TCAM_KEY_DISC)
+ cmd->data = RXH_DISCARD;
+ else
+
+ cmd->data = niu_flowkey_to_ethflow(np->parent->flow_key[class -
+ CLASS_CODE_USER_PROG1]);
+ return 0;
+}
+
+static int niu_set_hash_opts(struct net_device *dev, struct ethtool_rxnfc *cmd)
+{
+ struct niu *np = netdev_priv(dev);
+ u64 class;
+ u64 flow_key = 0;
+ unsigned long flags;
+
+ if (!niu_ethflow_to_class(cmd->flow_type, &class))
+ return -EINVAL;
+
+ if (class < CLASS_CODE_USER_PROG1 ||
+ class > CLASS_CODE_SCTP_IPV6)
+ return -EINVAL;
+
+ if (cmd->data & RXH_DISCARD) {
+ niu_lock_parent(np, flags);
+ flow_key = np->parent->tcam_key[class -
+ CLASS_CODE_USER_PROG1];
+ flow_key |= TCAM_KEY_DISC;
+ nw64(TCAM_KEY(class - CLASS_CODE_USER_PROG1), flow_key);
+ np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] = flow_key;
+ niu_unlock_parent(np, flags);
+ return 0;
+ } else {
+ /* Discard was set before, but is not set now */
+ if (np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] &
+ TCAM_KEY_DISC) {
+ niu_lock_parent(np, flags);
+ flow_key = np->parent->tcam_key[class -
+ CLASS_CODE_USER_PROG1];
+ flow_key &= ~TCAM_KEY_DISC;
+ nw64(TCAM_KEY(class - CLASS_CODE_USER_PROG1),
+ flow_key);
+ np->parent->tcam_key[class - CLASS_CODE_USER_PROG1] =
+ flow_key;
+ niu_unlock_parent(np, flags);
+ }
+ }
+
+ if (!niu_ethflow_to_flowkey(cmd->data, &flow_key))
+ return -EINVAL;
+
+ niu_lock_parent(np, flags);
+ nw64(FLOW_KEY(class - CLASS_CODE_USER_PROG1), flow_key);
+ np->parent->flow_key[class - CLASS_CODE_USER_PROG1] = flow_key;
+ niu_unlock_parent(np, flags);
+
+ return 0;
+}
+
static const struct {
const char string[ETH_GSTRING_LEN];
} niu_xmac_stat_keys[] = {
.get_stats_count = niu_get_stats_count,
.get_ethtool_stats = niu_get_ethtool_stats,
.phys_id = niu_phys_id,
+ .get_rxhash = niu_get_hash_opts,
+ .set_rxhash = niu_set_hash_opts,
};
static int niu_ldg_assign_ldn(struct niu *np, struct niu_parent *parent,
return 0;
}
-/* niu board models have a trailing dash version incremented
- * with HW rev change. Need to ingnore the dash version while
- * checking for match
- *
- * for example, for the 10G card the current vpd.board_model
- * is 501-5283-04, of which -04 is the dash version and have
- * to be ignored
- */
-static int niu_board_model_match(struct niu *np, const char *model)
-{
- return !strncmp(np->vpd.board_model, model, strlen(model));
-}
-
static int niu_pci_vpd_get_nports(struct niu *np)
{
int ports = 0;
- if ((niu_board_model_match(np, NIU_QGC_LP_BM_STR)) ||
- (niu_board_model_match(np, NIU_QGC_PEM_BM_STR)) ||
- (niu_board_model_match(np, NIU_ALONSO_BM_STR))) {
+ if ((!strcmp(np->vpd.model, NIU_QGC_LP_MDL_STR)) ||
+ (!strcmp(np->vpd.model, NIU_QGC_PEM_MDL_STR)) ||
+ (!strcmp(np->vpd.model, NIU_MARAMBA_MDL_STR)) ||
+ (!strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) ||
+ (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR))) {
ports = 4;
- } else if ((niu_board_model_match(np, NIU_2XGF_LP_BM_STR)) ||
- (niu_board_model_match(np, NIU_2XGF_PEM_BM_STR)) ||
- (niu_board_model_match(np, NIU_FOXXY_BM_STR)) ||
- (niu_board_model_match(np, NIU_2XGF_MRVL_BM_STR))) {
+ } else if ((!strcmp(np->vpd.model, NIU_2XGF_LP_MDL_STR)) ||
+ (!strcmp(np->vpd.model, NIU_2XGF_PEM_MDL_STR)) ||
+ (!strcmp(np->vpd.model, NIU_FOXXY_MDL_STR)) ||
+ (!strcmp(np->vpd.model, NIU_2XGF_MRVL_MDL_STR))) {
ports = 2;
}
return;
}
- if (!strcmp(np->vpd.model, "SUNW,CP3220") ||
- !strcmp(np->vpd.model, "SUNW,CP3260")) {
+ if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) ||
+ !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) {
np->flags |= NIU_FLAGS_10G;
np->flags &= ~NIU_FLAGS_FIBER;
np->flags |= NIU_FLAGS_XCVR_SERDES;
}
if (np->flags & NIU_FLAGS_10G)
np->mac_xcvr = MAC_XCVR_XPCS;
+ } else if (!strcmp(np->vpd.model, NIU_FOXXY_MDL_STR)) {
+ np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER |
+ NIU_FLAGS_HOTPLUG_PHY);
} else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) {
dev_err(np->device, PFX "Illegal phy string [%s].\n",
np->vpd.phy_type);
parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) &
ESPC_NUM_PORTS_MACS_VAL;
+ /* All of the current probing methods fail on
+ * Maramba on-board parts.
+ */
if (!parent->num_ports)
- return -ENODEV;
+ parent->num_ports = 4;
}
}
}
return 0;
if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) {
if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) &&
- ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011))
+ ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011) &&
+ ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8706))
return 0;
} else {
if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R)
u32 val;
int err;
-
- if (!strcmp(np->vpd.model, "SUNW,CP3220") ||
- !strcmp(np->vpd.model, "SUNW,CP3260")) {
+ if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) ||
+ !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) {
num_10g = 0;
num_1g = 2;
parent->plat_type = PLAT_TYPE_ATCA_CP3220;
phy_encode(PORT_TYPE_1G, 1) |
phy_encode(PORT_TYPE_1G, 2) |
phy_encode(PORT_TYPE_1G, 3));
+ } else if (!strcmp(np->vpd.model, NIU_FOXXY_MDL_STR)) {
+ num_10g = 2;
+ num_1g = 0;
+ parent->num_ports = 2;
+ val = (phy_encode(PORT_TYPE_10G, 0) |
+ phy_encode(PORT_TYPE_10G, 1));
} else {
err = fill_phy_probe_info(np, parent, info);
if (err)
struct device_node *dp;
const char *phy_type;
const u8 *mac_addr;
+ const char *model;
int prop_len;
if (np->parent->plat_type == PLAT_TYPE_NIU)
memcpy(dev->dev_addr, dev->perm_addr, dev->addr_len);
+ model = of_get_property(dp, "model", &prop_len);
+
+ if (model)
+ strcpy(np->vpd.model, model);
+
return 0;
#else
return -EINVAL;
struct of_device *op, const struct niu_ops *ops,
u8 port)
{
- struct net_device *dev = alloc_etherdev(sizeof(struct niu));
+ struct net_device *dev;
struct niu *np;
+ dev = alloc_etherdev_mq(sizeof(struct niu), NIU_NUM_TXCHAN);
if (!dev) {
dev_err(gen_dev, PFX "Etherdev alloc failed, aborting.\n");
return NULL;