diff options
Diffstat (limited to 'drivers/net/s2io.c')
-rw-r--r-- | drivers/net/s2io.c | 107 |
1 files changed, 67 insertions, 40 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 3885f6b83cc3..01e4b1c26a36 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
@@ -355,6 +355,16 @@ static char ethtool_driver_stats_keys[][ETH_GSTRING_LEN] = { | |||
355 | timer.data = (unsigned long) arg; \ | 355 | timer.data = (unsigned long) arg; \ |
356 | mod_timer(&timer, (jiffies + exp)) \ | 356 | mod_timer(&timer, (jiffies + exp)) \ |
357 | 357 | ||
358 | /* copy mac addr to def_mac_addr array */ | ||
359 | static void do_s2io_copy_mac_addr(struct s2io_nic *sp, int offset, u64 mac_addr) | ||
360 | { | ||
361 | sp->def_mac_addr[offset].mac_addr[5] = (u8) (mac_addr); | ||
362 | sp->def_mac_addr[offset].mac_addr[4] = (u8) (mac_addr >> 8); | ||
363 | sp->def_mac_addr[offset].mac_addr[3] = (u8) (mac_addr >> 16); | ||
364 | sp->def_mac_addr[offset].mac_addr[2] = (u8) (mac_addr >> 24); | ||
365 | sp->def_mac_addr[offset].mac_addr[1] = (u8) (mac_addr >> 32); | ||
366 | sp->def_mac_addr[offset].mac_addr[0] = (u8) (mac_addr >> 40); | ||
367 | } | ||
358 | /* Add the vlan */ | 368 | /* Add the vlan */ |
359 | static void s2io_vlan_rx_register(struct net_device *dev, | 369 | static void s2io_vlan_rx_register(struct net_device *dev, |
360 | struct vlan_group *grp) | 370 | struct vlan_group *grp) |
@@ -3412,7 +3422,7 @@ static void s2io_reset(struct s2io_nic * sp) | |||
3412 | } | 3422 | } |
3413 | 3423 | ||
3414 | /* restore the previously assigned mac address */ | 3424 | /* restore the previously assigned mac address */ |
3415 | s2io_set_mac_addr(sp->dev, (u8 *)&sp->def_mac_addr[0].mac_addr); | 3425 | do_s2io_prog_unicast(sp->dev, (u8 *)&sp->def_mac_addr[0].mac_addr); |
3416 | 3426 | ||
3417 | sp->device_enabled_once = FALSE; | 3427 | sp->device_enabled_once = FALSE; |
3418 | } | 3428 | } |
@@ -3843,7 +3853,7 @@ static int s2io_open(struct net_device *dev) | |||
3843 | goto hw_init_failed; | 3853 | goto hw_init_failed; |
3844 | } | 3854 | } |
3845 | 3855 | ||
3846 | if (s2io_set_mac_addr(dev, dev->dev_addr) == FAILURE) { | 3856 | if (do_s2io_prog_unicast(dev, dev->dev_addr) == FAILURE) { |
3847 | DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n"); | 3857 | DBG_PRINT(ERR_DBG, "Set Mac Address Failed\n"); |
3848 | s2io_card_down(sp); | 3858 | s2io_card_down(sp); |
3849 | err = -ENODEV; | 3859 | err = -ENODEV; |
@@ -4845,8 +4855,48 @@ static void s2io_set_multicast(struct net_device *dev) | |||
4845 | } | 4855 | } |
4846 | } | 4856 | } |
4847 | 4857 | ||
4858 | /* add unicast MAC address to CAM */ | ||
4859 | static int do_s2io_add_unicast(struct s2io_nic *sp, u64 addr, int off) | ||
4860 | { | ||
4861 | u64 val64; | ||
4862 | struct XENA_dev_config __iomem *bar0 = sp->bar0; | ||
4863 | |||
4864 | writeq(RMAC_ADDR_DATA0_MEM_ADDR(addr), | ||
4865 | &bar0->rmac_addr_data0_mem); | ||
4866 | |||
4867 | val64 = | ||
4868 | RMAC_ADDR_CMD_MEM_WE | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | | ||
4869 | RMAC_ADDR_CMD_MEM_OFFSET(off); | ||
4870 | writeq(val64, &bar0->rmac_addr_cmd_mem); | ||
4871 | |||
4872 | /* Wait till command completes */ | ||
4873 | if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, | ||
4874 | RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, | ||
4875 | S2IO_BIT_RESET)) { | ||
4876 | DBG_PRINT(INFO_DBG, "add_mac_addr failed\n"); | ||
4877 | return FAILURE; | ||
4878 | } | ||
4879 | return SUCCESS; | ||
4880 | } | ||
4881 | |||
4882 | /** | ||
4883 | * s2io_set_mac_addr driver entry point | ||
4884 | */ | ||
4885 | static int s2io_set_mac_addr(struct net_device *dev, void *p) | ||
4886 | { | ||
4887 | struct sockaddr *addr = p; | ||
4888 | |||
4889 | if (!is_valid_ether_addr(addr->sa_data)) | ||
4890 | return -EINVAL; | ||
4891 | |||
4892 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); | ||
4893 | |||
4894 | /* store the MAC address in CAM */ | ||
4895 | return (do_s2io_prog_unicast(dev, dev->dev_addr)); | ||
4896 | } | ||
4897 | |||
4848 | /** | 4898 | /** |
4849 | * s2io_set_mac_addr - Programs the Xframe mac address | 4899 | * do_s2io_prog_unicast - Programs the Xframe mac address |
4850 | * @dev : pointer to the device structure. | 4900 | * @dev : pointer to the device structure. |
4851 | * @addr: a uchar pointer to the new mac address which is to be set. | 4901 | * @addr: a uchar pointer to the new mac address which is to be set. |
4852 | * Description : This procedure will program the Xframe to receive | 4902 | * Description : This procedure will program the Xframe to receive |
@@ -4854,56 +4904,31 @@ static void s2io_set_multicast(struct net_device *dev) | |||
4854 | * Return value: SUCCESS on success and an appropriate (-)ve integer | 4904 | * Return value: SUCCESS on success and an appropriate (-)ve integer |
4855 | * as defined in errno.h file on failure. | 4905 | * as defined in errno.h file on failure. |
4856 | */ | 4906 | */ |
4857 | 4907 | static int do_s2io_prog_unicast(struct net_device *dev, u8 *addr) | |
4858 | static int s2io_set_mac_addr(struct net_device *dev, u8 * addr) | ||
4859 | { | 4908 | { |
4860 | struct s2io_nic *sp = dev->priv; | 4909 | struct s2io_nic *sp = dev->priv; |
4861 | struct XENA_dev_config __iomem *bar0 = sp->bar0; | 4910 | register u64 mac_addr = 0, perm_addr = 0; |
4862 | register u64 val64, mac_addr = 0; | ||
4863 | int i; | 4911 | int i; |
4864 | u64 old_mac_addr = 0; | ||
4865 | 4912 | ||
4866 | /* | 4913 | /* |
4867 | * Set the new MAC address as the new unicast filter and reflect this | 4914 | * Set the new MAC address as the new unicast filter and reflect this |
4868 | * change on the device address registered with the OS. It will be | 4915 | * change on the device address registered with the OS. It will be |
4869 | * at offset 0. | 4916 | * at offset 0. |
4870 | */ | 4917 | */ |
4871 | for (i = 0; i < ETH_ALEN; i++) { | 4918 | for (i = 0; i < ETH_ALEN; i++) { |
4872 | mac_addr <<= 8; | 4919 | mac_addr <<= 8; |
4873 | mac_addr |= addr[i]; | 4920 | mac_addr |= addr[i]; |
4874 | old_mac_addr <<= 8; | 4921 | perm_addr <<= 8; |
4875 | old_mac_addr |= sp->def_mac_addr[0].mac_addr[i]; | 4922 | perm_addr |= sp->def_mac_addr[0].mac_addr[i]; |
4876 | } | 4923 | } |
4877 | 4924 | ||
4878 | if(0 == mac_addr) | 4925 | /* check if the dev_addr is different than perm_addr */ |
4926 | if (mac_addr == perm_addr) | ||
4879 | return SUCCESS; | 4927 | return SUCCESS; |
4880 | 4928 | ||
4881 | /* Update the internal structure with this new mac address */ | 4929 | /* Update the internal structure with this new mac address */ |
4882 | if(mac_addr != old_mac_addr) { | 4930 | do_s2io_copy_mac_addr(sp, 0, mac_addr); |
4883 | memset(sp->def_mac_addr[0].mac_addr, 0, sizeof(ETH_ALEN)); | 4931 | return (do_s2io_add_unicast(sp, mac_addr, 0)); |
4884 | sp->def_mac_addr[0].mac_addr[5] = (u8) (mac_addr); | ||
4885 | sp->def_mac_addr[0].mac_addr[4] = (u8) (mac_addr >> 8); | ||
4886 | sp->def_mac_addr[0].mac_addr[3] = (u8) (mac_addr >> 16); | ||
4887 | sp->def_mac_addr[0].mac_addr[2] = (u8) (mac_addr >> 24); | ||
4888 | sp->def_mac_addr[0].mac_addr[1] = (u8) (mac_addr >> 32); | ||
4889 | sp->def_mac_addr[0].mac_addr[0] = (u8) (mac_addr >> 40); | ||
4890 | } | ||
4891 | |||
4892 | writeq(RMAC_ADDR_DATA0_MEM_ADDR(mac_addr), | ||
4893 | &bar0->rmac_addr_data0_mem); | ||
4894 | |||
4895 | val64 = | ||
4896 | RMAC_ADDR_CMD_MEM_WE | RMAC_ADDR_CMD_MEM_STROBE_NEW_CMD | | ||
4897 | RMAC_ADDR_CMD_MEM_OFFSET(0); | ||
4898 | writeq(val64, &bar0->rmac_addr_cmd_mem); | ||
4899 | /* Wait till command completes */ | ||
4900 | if (wait_for_cmd_complete(&bar0->rmac_addr_cmd_mem, | ||
4901 | RMAC_ADDR_CMD_MEM_STROBE_CMD_EXECUTING, S2IO_BIT_RESET)) { | ||
4902 | DBG_PRINT(ERR_DBG, "%s: set_mac_addr failed\n", dev->name); | ||
4903 | return FAILURE; | ||
4904 | } | ||
4905 | |||
4906 | return SUCCESS; | ||
4907 | } | 4932 | } |
4908 | 4933 | ||
4909 | /** | 4934 | /** |
@@ -7530,6 +7555,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
7530 | dev->get_stats = &s2io_get_stats; | 7555 | dev->get_stats = &s2io_get_stats; |
7531 | dev->set_multicast_list = &s2io_set_multicast; | 7556 | dev->set_multicast_list = &s2io_set_multicast; |
7532 | dev->do_ioctl = &s2io_ioctl; | 7557 | dev->do_ioctl = &s2io_ioctl; |
7558 | dev->set_mac_address = &s2io_set_mac_addr; | ||
7533 | dev->change_mtu = &s2io_change_mtu; | 7559 | dev->change_mtu = &s2io_change_mtu; |
7534 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); | 7560 | SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); |
7535 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; | 7561 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; |
@@ -7615,6 +7641,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
7615 | /* Set the factory defined MAC address initially */ | 7641 | /* Set the factory defined MAC address initially */ |
7616 | dev->addr_len = ETH_ALEN; | 7642 | dev->addr_len = ETH_ALEN; |
7617 | memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN); | 7643 | memcpy(dev->dev_addr, sp->def_mac_addr, ETH_ALEN); |
7644 | memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN); | ||
7618 | 7645 | ||
7619 | /* Store the values of the MSIX table in the s2io_nic structure */ | 7646 | /* Store the values of the MSIX table in the s2io_nic structure */ |
7620 | store_xmsi_data(sp); | 7647 | store_xmsi_data(sp); |