diff options
Diffstat (limited to 'drivers/net/cnic.c')
-rw-r--r-- | drivers/net/cnic.c | 209 |
1 files changed, 52 insertions, 157 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 302be4aa69d6..8cca60e43444 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c | |||
@@ -65,7 +65,14 @@ static LIST_HEAD(cnic_udev_list); | |||
65 | static DEFINE_RWLOCK(cnic_dev_lock); | 65 | static DEFINE_RWLOCK(cnic_dev_lock); |
66 | static DEFINE_MUTEX(cnic_lock); | 66 | static DEFINE_MUTEX(cnic_lock); |
67 | 67 | ||
68 | static struct cnic_ulp_ops *cnic_ulp_tbl[MAX_CNIC_ULP_TYPE]; | 68 | static struct cnic_ulp_ops __rcu *cnic_ulp_tbl[MAX_CNIC_ULP_TYPE]; |
69 | |||
70 | /* helper function, assuming cnic_lock is held */ | ||
71 | static inline struct cnic_ulp_ops *cnic_ulp_tbl_prot(int type) | ||
72 | { | ||
73 | return rcu_dereference_protected(cnic_ulp_tbl[type], | ||
74 | lockdep_is_held(&cnic_lock)); | ||
75 | } | ||
69 | 76 | ||
70 | static int cnic_service_bnx2(void *, void *); | 77 | static int cnic_service_bnx2(void *, void *); |
71 | static int cnic_service_bnx2x(void *, void *); | 78 | static int cnic_service_bnx2x(void *, void *); |
@@ -435,7 +442,7 @@ int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops) | |||
435 | return -EINVAL; | 442 | return -EINVAL; |
436 | } | 443 | } |
437 | mutex_lock(&cnic_lock); | 444 | mutex_lock(&cnic_lock); |
438 | if (cnic_ulp_tbl[ulp_type]) { | 445 | if (cnic_ulp_tbl_prot(ulp_type)) { |
439 | pr_err("%s: Type %d has already been registered\n", | 446 | pr_err("%s: Type %d has already been registered\n", |
440 | __func__, ulp_type); | 447 | __func__, ulp_type); |
441 | mutex_unlock(&cnic_lock); | 448 | mutex_unlock(&cnic_lock); |
@@ -478,7 +485,7 @@ int cnic_unregister_driver(int ulp_type) | |||
478 | return -EINVAL; | 485 | return -EINVAL; |
479 | } | 486 | } |
480 | mutex_lock(&cnic_lock); | 487 | mutex_lock(&cnic_lock); |
481 | ulp_ops = cnic_ulp_tbl[ulp_type]; | 488 | ulp_ops = cnic_ulp_tbl_prot(ulp_type); |
482 | if (!ulp_ops) { | 489 | if (!ulp_ops) { |
483 | pr_err("%s: Type %d has not been registered\n", | 490 | pr_err("%s: Type %d has not been registered\n", |
484 | __func__, ulp_type); | 491 | __func__, ulp_type); |
@@ -529,7 +536,7 @@ static int cnic_register_device(struct cnic_dev *dev, int ulp_type, | |||
529 | return -EINVAL; | 536 | return -EINVAL; |
530 | } | 537 | } |
531 | mutex_lock(&cnic_lock); | 538 | mutex_lock(&cnic_lock); |
532 | if (cnic_ulp_tbl[ulp_type] == NULL) { | 539 | if (cnic_ulp_tbl_prot(ulp_type) == NULL) { |
533 | pr_err("%s: Driver with type %d has not been registered\n", | 540 | pr_err("%s: Driver with type %d has not been registered\n", |
534 | __func__, ulp_type); | 541 | __func__, ulp_type); |
535 | mutex_unlock(&cnic_lock); | 542 | mutex_unlock(&cnic_lock); |
@@ -544,7 +551,7 @@ static int cnic_register_device(struct cnic_dev *dev, int ulp_type, | |||
544 | 551 | ||
545 | clear_bit(ULP_F_START, &cp->ulp_flags[ulp_type]); | 552 | clear_bit(ULP_F_START, &cp->ulp_flags[ulp_type]); |
546 | cp->ulp_handle[ulp_type] = ulp_ctx; | 553 | cp->ulp_handle[ulp_type] = ulp_ctx; |
547 | ulp_ops = cnic_ulp_tbl[ulp_type]; | 554 | ulp_ops = cnic_ulp_tbl_prot(ulp_type); |
548 | rcu_assign_pointer(cp->ulp_ops[ulp_type], ulp_ops); | 555 | rcu_assign_pointer(cp->ulp_ops[ulp_type], ulp_ops); |
549 | cnic_hold(dev); | 556 | cnic_hold(dev); |
550 | 557 | ||
@@ -2970,7 +2977,8 @@ static void cnic_ulp_stop(struct cnic_dev *dev) | |||
2970 | struct cnic_ulp_ops *ulp_ops; | 2977 | struct cnic_ulp_ops *ulp_ops; |
2971 | 2978 | ||
2972 | mutex_lock(&cnic_lock); | 2979 | mutex_lock(&cnic_lock); |
2973 | ulp_ops = cp->ulp_ops[if_type]; | 2980 | ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type], |
2981 | lockdep_is_held(&cnic_lock)); | ||
2974 | if (!ulp_ops) { | 2982 | if (!ulp_ops) { |
2975 | mutex_unlock(&cnic_lock); | 2983 | mutex_unlock(&cnic_lock); |
2976 | continue; | 2984 | continue; |
@@ -2994,7 +3002,8 @@ static void cnic_ulp_start(struct cnic_dev *dev) | |||
2994 | struct cnic_ulp_ops *ulp_ops; | 3002 | struct cnic_ulp_ops *ulp_ops; |
2995 | 3003 | ||
2996 | mutex_lock(&cnic_lock); | 3004 | mutex_lock(&cnic_lock); |
2997 | ulp_ops = cp->ulp_ops[if_type]; | 3005 | ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type], |
3006 | lockdep_is_held(&cnic_lock)); | ||
2998 | if (!ulp_ops || !ulp_ops->cnic_start) { | 3007 | if (!ulp_ops || !ulp_ops->cnic_start) { |
2999 | mutex_unlock(&cnic_lock); | 3008 | mutex_unlock(&cnic_lock); |
3000 | continue; | 3009 | continue; |
@@ -3058,7 +3067,7 @@ static void cnic_ulp_init(struct cnic_dev *dev) | |||
3058 | struct cnic_ulp_ops *ulp_ops; | 3067 | struct cnic_ulp_ops *ulp_ops; |
3059 | 3068 | ||
3060 | mutex_lock(&cnic_lock); | 3069 | mutex_lock(&cnic_lock); |
3061 | ulp_ops = cnic_ulp_tbl[i]; | 3070 | ulp_ops = cnic_ulp_tbl_prot(i); |
3062 | if (!ulp_ops || !ulp_ops->cnic_init) { | 3071 | if (!ulp_ops || !ulp_ops->cnic_init) { |
3063 | mutex_unlock(&cnic_lock); | 3072 | mutex_unlock(&cnic_lock); |
3064 | continue; | 3073 | continue; |
@@ -3082,7 +3091,7 @@ static void cnic_ulp_exit(struct cnic_dev *dev) | |||
3082 | struct cnic_ulp_ops *ulp_ops; | 3091 | struct cnic_ulp_ops *ulp_ops; |
3083 | 3092 | ||
3084 | mutex_lock(&cnic_lock); | 3093 | mutex_lock(&cnic_lock); |
3085 | ulp_ops = cnic_ulp_tbl[i]; | 3094 | ulp_ops = cnic_ulp_tbl_prot(i); |
3086 | if (!ulp_ops || !ulp_ops->cnic_exit) { | 3095 | if (!ulp_ops || !ulp_ops->cnic_exit) { |
3087 | mutex_unlock(&cnic_lock); | 3096 | mutex_unlock(&cnic_lock); |
3088 | continue; | 3097 | continue; |
@@ -3398,17 +3407,14 @@ static int cnic_get_v4_route(struct sockaddr_in *dst_addr, | |||
3398 | struct dst_entry **dst) | 3407 | struct dst_entry **dst) |
3399 | { | 3408 | { |
3400 | #if defined(CONFIG_INET) | 3409 | #if defined(CONFIG_INET) |
3401 | struct flowi fl; | ||
3402 | int err; | ||
3403 | struct rtable *rt; | 3410 | struct rtable *rt; |
3404 | 3411 | ||
3405 | memset(&fl, 0, sizeof(fl)); | 3412 | rt = ip_route_output(&init_net, dst_addr->sin_addr.s_addr, 0, 0, 0); |
3406 | fl.nl_u.ip4_u.daddr = dst_addr->sin_addr.s_addr; | 3413 | if (!IS_ERR(rt)) { |
3407 | |||
3408 | err = ip_route_output_key(&init_net, &rt, &fl); | ||
3409 | if (!err) | ||
3410 | *dst = &rt->dst; | 3414 | *dst = &rt->dst; |
3411 | return err; | 3415 | return 0; |
3416 | } | ||
3417 | return PTR_ERR(rt); | ||
3412 | #else | 3418 | #else |
3413 | return -ENETUNREACH; | 3419 | return -ENETUNREACH; |
3414 | #endif | 3420 | #endif |
@@ -3418,14 +3424,14 @@ static int cnic_get_v6_route(struct sockaddr_in6 *dst_addr, | |||
3418 | struct dst_entry **dst) | 3424 | struct dst_entry **dst) |
3419 | { | 3425 | { |
3420 | #if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE)) | 3426 | #if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE)) |
3421 | struct flowi fl; | 3427 | struct flowi6 fl6; |
3422 | 3428 | ||
3423 | memset(&fl, 0, sizeof(fl)); | 3429 | memset(&fl6, 0, sizeof(fl6)); |
3424 | ipv6_addr_copy(&fl.fl6_dst, &dst_addr->sin6_addr); | 3430 | ipv6_addr_copy(&fl6.daddr, &dst_addr->sin6_addr); |
3425 | if (ipv6_addr_type(&fl.fl6_dst) & IPV6_ADDR_LINKLOCAL) | 3431 | if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL) |
3426 | fl.oif = dst_addr->sin6_scope_id; | 3432 | fl6.flowi6_oif = dst_addr->sin6_scope_id; |
3427 | 3433 | ||
3428 | *dst = ip6_route_output(&init_net, NULL, &fl); | 3434 | *dst = ip6_route_output(&init_net, NULL, &fl6); |
3429 | if (*dst) | 3435 | if (*dst) |
3430 | return 0; | 3436 | return 0; |
3431 | #endif | 3437 | #endif |
@@ -4187,6 +4193,14 @@ static void cnic_enable_bnx2_int(struct cnic_dev *dev) | |||
4187 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx); | 4193 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx); |
4188 | } | 4194 | } |
4189 | 4195 | ||
4196 | static void cnic_get_bnx2_iscsi_info(struct cnic_dev *dev) | ||
4197 | { | ||
4198 | u32 max_conn; | ||
4199 | |||
4200 | max_conn = cnic_reg_rd_ind(dev, BNX2_FW_MAX_ISCSI_CONN); | ||
4201 | dev->max_iscsi_conn = max_conn; | ||
4202 | } | ||
4203 | |||
4190 | static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev) | 4204 | static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev) |
4191 | { | 4205 | { |
4192 | struct cnic_local *cp = dev->cnic_priv; | 4206 | struct cnic_local *cp = dev->cnic_priv; |
@@ -4511,6 +4525,8 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) | |||
4511 | return err; | 4525 | return err; |
4512 | } | 4526 | } |
4513 | 4527 | ||
4528 | cnic_get_bnx2_iscsi_info(dev); | ||
4529 | |||
4514 | return 0; | 4530 | return 0; |
4515 | } | 4531 | } |
4516 | 4532 | ||
@@ -4722,129 +4738,6 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, | |||
4722 | cp->rx_cons = *cp->rx_cons_ptr; | 4738 | cp->rx_cons = *cp->rx_cons_ptr; |
4723 | } | 4739 | } |
4724 | 4740 | ||
4725 | static int cnic_read_bnx2x_iscsi_mac(struct cnic_dev *dev, u32 upper_addr, | ||
4726 | u32 lower_addr) | ||
4727 | { | ||
4728 | u32 val; | ||
4729 | u8 mac[6]; | ||
4730 | |||
4731 | val = CNIC_RD(dev, upper_addr); | ||
4732 | |||
4733 | mac[0] = (u8) (val >> 8); | ||
4734 | mac[1] = (u8) val; | ||
4735 | |||
4736 | val = CNIC_RD(dev, lower_addr); | ||
4737 | |||
4738 | mac[2] = (u8) (val >> 24); | ||
4739 | mac[3] = (u8) (val >> 16); | ||
4740 | mac[4] = (u8) (val >> 8); | ||
4741 | mac[5] = (u8) val; | ||
4742 | |||
4743 | if (is_valid_ether_addr(mac)) { | ||
4744 | memcpy(dev->mac_addr, mac, 6); | ||
4745 | return 0; | ||
4746 | } else { | ||
4747 | return -EINVAL; | ||
4748 | } | ||
4749 | } | ||
4750 | |||
4751 | static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev) | ||
4752 | { | ||
4753 | struct cnic_local *cp = dev->cnic_priv; | ||
4754 | u32 base, base2, addr, addr1, val; | ||
4755 | int port = CNIC_PORT(cp); | ||
4756 | |||
4757 | dev->max_iscsi_conn = 0; | ||
4758 | base = CNIC_RD(dev, MISC_REG_SHARED_MEM_ADDR); | ||
4759 | if (base == 0) | ||
4760 | return; | ||
4761 | |||
4762 | base2 = CNIC_RD(dev, (CNIC_PATH(cp) ? MISC_REG_GENERIC_CR_1 : | ||
4763 | MISC_REG_GENERIC_CR_0)); | ||
4764 | addr = BNX2X_SHMEM_ADDR(base, | ||
4765 | dev_info.port_hw_config[port].iscsi_mac_upper); | ||
4766 | |||
4767 | addr1 = BNX2X_SHMEM_ADDR(base, | ||
4768 | dev_info.port_hw_config[port].iscsi_mac_lower); | ||
4769 | |||
4770 | cnic_read_bnx2x_iscsi_mac(dev, addr, addr1); | ||
4771 | |||
4772 | addr = BNX2X_SHMEM_ADDR(base, validity_map[port]); | ||
4773 | val = CNIC_RD(dev, addr); | ||
4774 | |||
4775 | if (!(val & SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT)) { | ||
4776 | u16 val16; | ||
4777 | |||
4778 | addr = BNX2X_SHMEM_ADDR(base, | ||
4779 | drv_lic_key[port].max_iscsi_init_conn); | ||
4780 | val16 = CNIC_RD16(dev, addr); | ||
4781 | |||
4782 | if (val16) | ||
4783 | val16 ^= 0x1e1e; | ||
4784 | dev->max_iscsi_conn = val16; | ||
4785 | } | ||
4786 | |||
4787 | if (BNX2X_CHIP_IS_E2(cp->chip_id)) | ||
4788 | dev->max_fcoe_conn = BNX2X_FCOE_NUM_CONNECTIONS; | ||
4789 | |||
4790 | if (BNX2X_CHIP_IS_E1H(cp->chip_id) || BNX2X_CHIP_IS_E2(cp->chip_id)) { | ||
4791 | int func = CNIC_FUNC(cp); | ||
4792 | u32 mf_cfg_addr; | ||
4793 | |||
4794 | if (BNX2X_SHMEM2_HAS(base2, mf_cfg_addr)) | ||
4795 | mf_cfg_addr = CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base2, | ||
4796 | mf_cfg_addr)); | ||
4797 | else | ||
4798 | mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET; | ||
4799 | |||
4800 | if (BNX2X_CHIP_IS_E2(cp->chip_id)) { | ||
4801 | /* Must determine if the MF is SD vs SI mode */ | ||
4802 | addr = BNX2X_SHMEM_ADDR(base, | ||
4803 | dev_info.shared_feature_config.config); | ||
4804 | val = CNIC_RD(dev, addr); | ||
4805 | if ((val & SHARED_FEAT_CFG_FORCE_SF_MODE_MASK) == | ||
4806 | SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT) { | ||
4807 | int rc; | ||
4808 | |||
4809 | /* MULTI_FUNCTION_SI mode */ | ||
4810 | addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr, | ||
4811 | func_ext_config[func].func_cfg); | ||
4812 | val = CNIC_RD(dev, addr); | ||
4813 | if (!(val & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD)) | ||
4814 | dev->max_iscsi_conn = 0; | ||
4815 | |||
4816 | if (!(val & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD)) | ||
4817 | dev->max_fcoe_conn = 0; | ||
4818 | |||
4819 | addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr, | ||
4820 | func_ext_config[func]. | ||
4821 | iscsi_mac_addr_upper); | ||
4822 | addr1 = BNX2X_MF_CFG_ADDR(mf_cfg_addr, | ||
4823 | func_ext_config[func]. | ||
4824 | iscsi_mac_addr_lower); | ||
4825 | rc = cnic_read_bnx2x_iscsi_mac(dev, addr, | ||
4826 | addr1); | ||
4827 | if (rc && func > 1) | ||
4828 | dev->max_iscsi_conn = 0; | ||
4829 | |||
4830 | return; | ||
4831 | } | ||
4832 | } | ||
4833 | |||
4834 | addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr, | ||
4835 | func_mf_config[func].e1hov_tag); | ||
4836 | |||
4837 | val = CNIC_RD(dev, addr); | ||
4838 | val &= FUNC_MF_CFG_E1HOV_TAG_MASK; | ||
4839 | if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) { | ||
4840 | dev->max_fcoe_conn = 0; | ||
4841 | dev->max_iscsi_conn = 0; | ||
4842 | } | ||
4843 | } | ||
4844 | if (!is_valid_ether_addr(dev->mac_addr)) | ||
4845 | dev->max_iscsi_conn = 0; | ||
4846 | } | ||
4847 | |||
4848 | static void cnic_init_bnx2x_kcq(struct cnic_dev *dev) | 4741 | static void cnic_init_bnx2x_kcq(struct cnic_dev *dev) |
4849 | { | 4742 | { |
4850 | struct cnic_local *cp = dev->cnic_priv; | 4743 | struct cnic_local *cp = dev->cnic_priv; |
@@ -4926,8 +4819,6 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) | |||
4926 | 4819 | ||
4927 | cnic_init_bnx2x_kcq(dev); | 4820 | cnic_init_bnx2x_kcq(dev); |
4928 | 4821 | ||
4929 | cnic_get_bnx2x_iscsi_info(dev); | ||
4930 | |||
4931 | /* Only 1 EQ */ | 4822 | /* Only 1 EQ */ |
4932 | CNIC_WR16(dev, cp->kcq1.io_addr, MAX_KCQ_IDX); | 4823 | CNIC_WR16(dev, cp->kcq1.io_addr, MAX_KCQ_IDX); |
4933 | CNIC_WR(dev, BAR_CSTRORM_INTMEM + | 4824 | CNIC_WR(dev, BAR_CSTRORM_INTMEM + |
@@ -5281,15 +5172,11 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev) | |||
5281 | 5172 | ||
5282 | dev_hold(dev); | 5173 | dev_hold(dev); |
5283 | pci_dev_get(pdev); | 5174 | pci_dev_get(pdev); |
5284 | if (pdev->device == PCI_DEVICE_ID_NX2_5709 || | 5175 | if ((pdev->device == PCI_DEVICE_ID_NX2_5709 || |
5285 | pdev->device == PCI_DEVICE_ID_NX2_5709S) { | 5176 | pdev->device == PCI_DEVICE_ID_NX2_5709S) && |
5286 | u8 rev; | 5177 | (pdev->revision < 0x10)) { |
5287 | 5178 | pci_dev_put(pdev); | |
5288 | pci_read_config_byte(pdev, PCI_REVISION_ID, &rev); | 5179 | goto cnic_err; |
5289 | if (rev < 0x10) { | ||
5290 | pci_dev_put(pdev); | ||
5291 | goto cnic_err; | ||
5292 | } | ||
5293 | } | 5180 | } |
5294 | pci_dev_put(pdev); | 5181 | pci_dev_put(pdev); |
5295 | 5182 | ||
@@ -5360,6 +5247,14 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev) | |||
5360 | cdev->pcidev = pdev; | 5247 | cdev->pcidev = pdev; |
5361 | cp->chip_id = ethdev->chip_id; | 5248 | cp->chip_id = ethdev->chip_id; |
5362 | 5249 | ||
5250 | if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI)) | ||
5251 | cdev->max_iscsi_conn = ethdev->max_iscsi_conn; | ||
5252 | if (BNX2X_CHIP_IS_E2(cp->chip_id) && | ||
5253 | !(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE)) | ||
5254 | cdev->max_fcoe_conn = ethdev->max_fcoe_conn; | ||
5255 | |||
5256 | memcpy(cdev->mac_addr, ethdev->iscsi_mac, 6); | ||
5257 | |||
5363 | cp->cnic_ops = &cnic_bnx2x_ops; | 5258 | cp->cnic_ops = &cnic_bnx2x_ops; |
5364 | cp->start_hw = cnic_start_bnx2x_hw; | 5259 | cp->start_hw = cnic_start_bnx2x_hw; |
5365 | cp->stop_hw = cnic_stop_bnx2x_hw; | 5260 | cp->stop_hw = cnic_stop_bnx2x_hw; |