diff options
Diffstat (limited to 'drivers/net/ethernet/ibm')
-rw-r--r-- | drivers/net/ethernet/ibm/emac/core.c | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/ibm/emac/emac.h | 13 | ||||
-rw-r--r-- | drivers/net/ethernet/ibm/emac/phy.c | 10 | ||||
-rw-r--r-- | drivers/net/ethernet/ibm/emac/rgmii.c | 43 | ||||
-rw-r--r-- | drivers/net/ethernet/ibm/emac/zmii.c | 38 | ||||
-rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.c | 36 | ||||
-rw-r--r-- | drivers/net/ethernet/ibm/ibmvnic.h | 2 |
7 files changed, 76 insertions, 86 deletions
diff --git a/drivers/net/ethernet/ibm/emac/core.c b/drivers/net/ethernet/ibm/emac/core.c index 241db3199b88..354c0982847b 100644 --- a/drivers/net/ethernet/ibm/emac/core.c +++ b/drivers/net/ethernet/ibm/emac/core.c @@ -199,18 +199,18 @@ static void __emac_set_multicast_list(struct emac_instance *dev); static inline int emac_phy_supports_gige(int phy_mode) { - return phy_mode == PHY_MODE_GMII || - phy_mode == PHY_MODE_RGMII || - phy_mode == PHY_MODE_SGMII || - phy_mode == PHY_MODE_TBI || - phy_mode == PHY_MODE_RTBI; + return phy_interface_mode_is_rgmii(phy_mode) || + phy_mode == PHY_INTERFACE_MODE_GMII || + phy_mode == PHY_INTERFACE_MODE_SGMII || + phy_mode == PHY_INTERFACE_MODE_TBI || + phy_mode == PHY_INTERFACE_MODE_RTBI; } static inline int emac_phy_gpcs(int phy_mode) { - return phy_mode == PHY_MODE_SGMII || - phy_mode == PHY_MODE_TBI || - phy_mode == PHY_MODE_RTBI; + return phy_mode == PHY_INTERFACE_MODE_SGMII || + phy_mode == PHY_INTERFACE_MODE_TBI || + phy_mode == PHY_INTERFACE_MODE_RTBI; } static inline void emac_tx_enable(struct emac_instance *dev) @@ -2871,7 +2871,7 @@ static int emac_init_config(struct emac_instance *dev) /* PHY mode needs some decoding */ dev->phy_mode = of_get_phy_mode(np); if (dev->phy_mode < 0) - dev->phy_mode = PHY_MODE_NA; + dev->phy_mode = PHY_INTERFACE_MODE_NA; /* Check EMAC version */ if (of_device_is_compatible(np, "ibm,emac4sync")) { @@ -3174,7 +3174,7 @@ static int emac_probe(struct platform_device *ofdev) printk(KERN_INFO "%s: EMAC-%d %pOF, MAC %pM\n", ndev->name, dev->cell_index, np, ndev->dev_addr); - if (dev->phy_mode == PHY_MODE_SGMII) + if (dev->phy_mode == PHY_INTERFACE_MODE_SGMII) printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name); if (dev->phy.address >= 0) diff --git a/drivers/net/ethernet/ibm/emac/emac.h b/drivers/net/ethernet/ibm/emac/emac.h index c26d2631ca30..e2f80cca9bed 100644 --- a/drivers/net/ethernet/ibm/emac/emac.h +++ b/drivers/net/ethernet/ibm/emac/emac.h @@ -104,19 +104,6 @@ struct emac_regs { } u1; }; -/* - * PHY mode settings (EMAC <-> ZMII/RGMII bridge <-> PHY) - */ -#define PHY_MODE_NA PHY_INTERFACE_MODE_NA -#define PHY_MODE_MII PHY_INTERFACE_MODE_MII -#define PHY_MODE_RMII PHY_INTERFACE_MODE_RMII -#define PHY_MODE_SMII PHY_INTERFACE_MODE_SMII -#define PHY_MODE_RGMII PHY_INTERFACE_MODE_RGMII -#define PHY_MODE_TBI PHY_INTERFACE_MODE_TBI -#define PHY_MODE_GMII PHY_INTERFACE_MODE_GMII -#define PHY_MODE_RTBI PHY_INTERFACE_MODE_RTBI -#define PHY_MODE_SGMII PHY_INTERFACE_MODE_SGMII - /* EMACx_MR0 */ #define EMAC_MR0_RXI 0x80000000 #define EMAC_MR0_TXI 0x40000000 diff --git a/drivers/net/ethernet/ibm/emac/phy.c b/drivers/net/ethernet/ibm/emac/phy.c index 35865d05fccd..aa070c063e48 100644 --- a/drivers/net/ethernet/ibm/emac/phy.c +++ b/drivers/net/ethernet/ibm/emac/phy.c @@ -96,7 +96,7 @@ int emac_mii_reset_gpcs(struct mii_phy *phy) if ((val & BMCR_ISOLATE) && limit > 0) gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE); - if (limit > 0 && phy->mode == PHY_MODE_SGMII) { + if (limit > 0 && phy->mode == PHY_INTERFACE_MODE_SGMII) { /* Configure GPCS interface to recommended setting for SGMII */ gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */ gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */ @@ -313,16 +313,16 @@ static int cis8201_init(struct mii_phy *phy) epcr &= ~EPCR_MODE_MASK; switch (phy->mode) { - case PHY_MODE_TBI: + case PHY_INTERFACE_MODE_TBI: epcr |= EPCR_TBI_MODE; break; - case PHY_MODE_RTBI: + case PHY_INTERFACE_MODE_RTBI: epcr |= EPCR_RTBI_MODE; break; - case PHY_MODE_GMII: + case PHY_INTERFACE_MODE_GMII: epcr |= EPCR_GMII_MODE; break; - case PHY_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII: default: epcr |= EPCR_RGMII_MODE; } diff --git a/drivers/net/ethernet/ibm/emac/rgmii.c b/drivers/net/ethernet/ibm/emac/rgmii.c index c4a1ac38bba8..00f5999de3cf 100644 --- a/drivers/net/ethernet/ibm/emac/rgmii.c +++ b/drivers/net/ethernet/ibm/emac/rgmii.c @@ -52,43 +52,28 @@ /* RGMII bridge supports only GMII/TBI and RGMII/RTBI PHYs */ static inline int rgmii_valid_mode(int phy_mode) { - return phy_mode == PHY_MODE_GMII || - phy_mode == PHY_MODE_MII || - phy_mode == PHY_MODE_RGMII || - phy_mode == PHY_MODE_TBI || - phy_mode == PHY_MODE_RTBI; -} - -static inline const char *rgmii_mode_name(int mode) -{ - switch (mode) { - case PHY_MODE_RGMII: - return "RGMII"; - case PHY_MODE_TBI: - return "TBI"; - case PHY_MODE_GMII: - return "GMII"; - case PHY_MODE_MII: - return "MII"; - case PHY_MODE_RTBI: - return "RTBI"; - default: - BUG(); - } + return phy_interface_mode_is_rgmii(phy_mode) || + phy_mode == PHY_INTERFACE_MODE_GMII || + phy_mode == PHY_INTERFACE_MODE_MII || + phy_mode == PHY_INTERFACE_MODE_TBI || + phy_mode == PHY_INTERFACE_MODE_RTBI; } static inline u32 rgmii_mode_mask(int mode, int input) { switch (mode) { - case PHY_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + case PHY_INTERFACE_MODE_RGMII_RXID: + case PHY_INTERFACE_MODE_RGMII_TXID: return RGMII_FER_RGMII(input); - case PHY_MODE_TBI: + case PHY_INTERFACE_MODE_TBI: return RGMII_FER_TBI(input); - case PHY_MODE_GMII: + case PHY_INTERFACE_MODE_GMII: return RGMII_FER_GMII(input); - case PHY_MODE_MII: + case PHY_INTERFACE_MODE_MII: return RGMII_FER_MII(input); - case PHY_MODE_RTBI: + case PHY_INTERFACE_MODE_RTBI: return RGMII_FER_RTBI(input); default: BUG(); @@ -115,7 +100,7 @@ int rgmii_attach(struct platform_device *ofdev, int input, int mode) out_be32(&p->fer, in_be32(&p->fer) | rgmii_mode_mask(mode, input)); printk(KERN_NOTICE "%pOF: input %d in %s mode\n", - ofdev->dev.of_node, input, rgmii_mode_name(mode)); + ofdev->dev.of_node, input, phy_modes(mode)); ++dev->users; diff --git a/drivers/net/ethernet/ibm/emac/zmii.c b/drivers/net/ethernet/ibm/emac/zmii.c index 89c42d362292..fdcc734541fe 100644 --- a/drivers/net/ethernet/ibm/emac/zmii.c +++ b/drivers/net/ethernet/ibm/emac/zmii.c @@ -49,20 +49,20 @@ */ static inline int zmii_valid_mode(int mode) { - return mode == PHY_MODE_MII || - mode == PHY_MODE_RMII || - mode == PHY_MODE_SMII || - mode == PHY_MODE_NA; + return mode == PHY_INTERFACE_MODE_MII || + mode == PHY_INTERFACE_MODE_RMII || + mode == PHY_INTERFACE_MODE_SMII || + mode == PHY_INTERFACE_MODE_NA; } static inline const char *zmii_mode_name(int mode) { switch (mode) { - case PHY_MODE_MII: + case PHY_INTERFACE_MODE_MII: return "MII"; - case PHY_MODE_RMII: + case PHY_INTERFACE_MODE_RMII: return "RMII"; - case PHY_MODE_SMII: + case PHY_INTERFACE_MODE_SMII: return "SMII"; default: BUG(); @@ -72,11 +72,11 @@ static inline const char *zmii_mode_name(int mode) static inline u32 zmii_mode_mask(int mode, int input) { switch (mode) { - case PHY_MODE_MII: + case PHY_INTERFACE_MODE_MII: return ZMII_FER_MII(input); - case PHY_MODE_RMII: + case PHY_INTERFACE_MODE_RMII: return ZMII_FER_RMII(input); - case PHY_MODE_SMII: + case PHY_INTERFACE_MODE_SMII: return ZMII_FER_SMII(input); default: return 0; @@ -106,27 +106,27 @@ int zmii_attach(struct platform_device *ofdev, int input, int *mode) * Please, always specify PHY mode in your board port to avoid * any surprises. */ - if (dev->mode == PHY_MODE_NA) { - if (*mode == PHY_MODE_NA) { + if (dev->mode == PHY_INTERFACE_MODE_NA) { + if (*mode == PHY_INTERFACE_MODE_NA) { u32 r = dev->fer_save; ZMII_DBG(dev, "autodetecting mode, FER = 0x%08x" NL, r); if (r & (ZMII_FER_MII(0) | ZMII_FER_MII(1))) - dev->mode = PHY_MODE_MII; + dev->mode = PHY_INTERFACE_MODE_MII; else if (r & (ZMII_FER_RMII(0) | ZMII_FER_RMII(1))) - dev->mode = PHY_MODE_RMII; + dev->mode = PHY_INTERFACE_MODE_RMII; else - dev->mode = PHY_MODE_SMII; - } else + dev->mode = PHY_INTERFACE_MODE_SMII; + } else { dev->mode = *mode; - + } printk(KERN_NOTICE "%pOF: bridge in %s mode\n", ofdev->dev.of_node, zmii_mode_name(dev->mode)); } else { /* All inputs must use the same mode */ - if (*mode != PHY_MODE_NA && *mode != dev->mode) { + if (*mode != PHY_INTERFACE_MODE_NA && *mode != dev->mode) { printk(KERN_ERR "%pOF: invalid mode %d specified for input %d\n", ofdev->dev.of_node, *mode, input); @@ -246,7 +246,7 @@ static int zmii_probe(struct platform_device *ofdev) mutex_init(&dev->lock); dev->ofdev = ofdev; - dev->mode = PHY_MODE_NA; + dev->mode = PHY_INTERFACE_MODE_NA; rc = -ENXIO; if (of_address_to_resource(np, 0, ®s)) { diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index b65f5f3ac034..8c3058d5d191 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -59,6 +59,7 @@ #include <linux/mm.h> #include <linux/ethtool.h> #include <linux/proc_fs.h> +#include <linux/if_arp.h> #include <linux/in.h> #include <linux/ip.h> #include <linux/ipv6.h> @@ -1177,6 +1178,9 @@ static int build_hdr_data(u8 hdr_field, struct sk_buff *skb, hdr_len[2] = tcp_hdrlen(skb); else if (ipv6_hdr(skb)->nexthdr == IPPROTO_UDP) hdr_len[2] = sizeof(struct udphdr); + } else if (skb->protocol == htons(ETH_P_ARP)) { + hdr_len[1] = arp_hdr_len(skb->dev); + hdr_len[2] = 0; } memset(hdr_data, 0, 120); @@ -1412,7 +1416,8 @@ static int ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev) /* determine if l2/3/4 headers are sent to firmware */ if ((*hdrs >> 7) & 1 && (skb->protocol == htons(ETH_P_IP) || - skb->protocol == htons(ETH_P_IPV6))) { + skb->protocol == htons(ETH_P_IPV6) || + skb->protocol == htons(ETH_P_ARP))) { build_hdr_descs_arr(tx_buff, &num_entries, *hdrs); tx_crq.v1.n_crq_elem = num_entries; tx_buff->indir_arr[0] = tx_crq; @@ -1543,15 +1548,19 @@ static int __ibmvnic_set_mac(struct net_device *netdev, struct sockaddr *p) crq.change_mac_addr.first = IBMVNIC_CRQ_CMD; crq.change_mac_addr.cmd = CHANGE_MAC_ADDR; ether_addr_copy(&crq.change_mac_addr.mac_addr[0], addr->sa_data); + + init_completion(&adapter->fw_done); ibmvnic_send_crq(adapter, &crq); + wait_for_completion(&adapter->fw_done); /* netdev->dev_addr is changed in handle_change_mac_rsp function */ - return 0; + return adapter->fw_done_rc ? -EIO : 0; } static int ibmvnic_set_mac(struct net_device *netdev, void *p) { struct ibmvnic_adapter *adapter = netdev_priv(netdev); struct sockaddr *addr = p; + int rc; if (adapter->state == VNIC_PROBED) { memcpy(&adapter->desired.mac, addr, sizeof(struct sockaddr)); @@ -1559,9 +1568,9 @@ static int ibmvnic_set_mac(struct net_device *netdev, void *p) return 0; } - __ibmvnic_set_mac(netdev, addr); + rc = __ibmvnic_set_mac(netdev, addr); - return 0; + return rc; } /** @@ -2484,6 +2493,12 @@ static irqreturn_t ibmvnic_interrupt_rx(int irq, void *instance) struct ibmvnic_sub_crq_queue *scrq = instance; struct ibmvnic_adapter *adapter = scrq->adapter; + /* When booting a kdump kernel we can hit pending interrupts + * prior to completing driver initialization. + */ + if (unlikely(adapter->state != VNIC_OPEN)) + return IRQ_NONE; + adapter->rx_stats_buffers[scrq->scrq_num].interrupts++; if (napi_schedule_prep(&adapter->napi[scrq->scrq_num])) { @@ -3558,8 +3573,8 @@ static void handle_error_indication(union ibmvnic_crq *crq, ibmvnic_reset(adapter, VNIC_RESET_NON_FATAL); } -static void handle_change_mac_rsp(union ibmvnic_crq *crq, - struct ibmvnic_adapter *adapter) +static int handle_change_mac_rsp(union ibmvnic_crq *crq, + struct ibmvnic_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct device *dev = &adapter->vdev->dev; @@ -3568,10 +3583,13 @@ static void handle_change_mac_rsp(union ibmvnic_crq *crq, rc = crq->change_mac_addr_rsp.rc.code; if (rc) { dev_err(dev, "Error %ld in CHANGE_MAC_ADDR_RSP\n", rc); - return; + goto out; } memcpy(netdev->dev_addr, &crq->change_mac_addr_rsp.mac_addr[0], ETH_ALEN); +out: + complete(&adapter->fw_done); + return rc; } static void handle_request_cap_rsp(union ibmvnic_crq *crq, @@ -4031,7 +4049,7 @@ static void ibmvnic_handle_crq(union ibmvnic_crq *crq, break; case CHANGE_MAC_ADDR_RSP: netdev_dbg(netdev, "Got MAC address change Response\n"); - handle_change_mac_rsp(crq, adapter); + adapter->fw_done_rc = handle_change_mac_rsp(crq, adapter); break; case ERROR_INDICATION: netdev_dbg(netdev, "Got Error Indication\n"); @@ -4335,7 +4353,7 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id) } netdev = alloc_etherdev_mq(sizeof(struct ibmvnic_adapter), - IBMVNIC_MAX_TX_QUEUES); + IBMVNIC_MAX_QUEUES); if (!netdev) return -ENOMEM; diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index 3aec42118db2..fe21a6e2ddae 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -39,7 +39,7 @@ #define IBMVNIC_RX_WEIGHT 16 /* when changing this, update IBMVNIC_IO_ENTITLEMENT_DEFAULT */ #define IBMVNIC_BUFFS_PER_POOL 100 -#define IBMVNIC_MAX_TX_QUEUES 5 +#define IBMVNIC_MAX_QUEUES 10 #define IBMVNIC_TSO_BUF_SZ 65536 #define IBMVNIC_TSO_BUFS 64 |