diff options
Diffstat (limited to 'drivers/net/cnic.c')
-rw-r--r-- | drivers/net/cnic.c | 182 |
1 files changed, 42 insertions, 140 deletions
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 263a2944566f..2d2d28f58e91 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 | ||
@@ -699,13 +706,13 @@ static void cnic_free_dma(struct cnic_dev *dev, struct cnic_dma *dma) | |||
699 | static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma) | 706 | static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma) |
700 | { | 707 | { |
701 | int i; | 708 | int i; |
702 | u32 *page_table = dma->pgtbl; | 709 | __le32 *page_table = (__le32 *) dma->pgtbl; |
703 | 710 | ||
704 | for (i = 0; i < dma->num_pages; i++) { | 711 | for (i = 0; i < dma->num_pages; i++) { |
705 | /* Each entry needs to be in big endian format. */ | 712 | /* Each entry needs to be in big endian format. */ |
706 | *page_table = (u32) ((u64) dma->pg_map_arr[i] >> 32); | 713 | *page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32); |
707 | page_table++; | 714 | page_table++; |
708 | *page_table = (u32) dma->pg_map_arr[i]; | 715 | *page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff); |
709 | page_table++; | 716 | page_table++; |
710 | } | 717 | } |
711 | } | 718 | } |
@@ -713,13 +720,13 @@ static void cnic_setup_page_tbl(struct cnic_dev *dev, struct cnic_dma *dma) | |||
713 | static void cnic_setup_page_tbl_le(struct cnic_dev *dev, struct cnic_dma *dma) | 720 | static void cnic_setup_page_tbl_le(struct cnic_dev *dev, struct cnic_dma *dma) |
714 | { | 721 | { |
715 | int i; | 722 | int i; |
716 | u32 *page_table = dma->pgtbl; | 723 | __le32 *page_table = (__le32 *) dma->pgtbl; |
717 | 724 | ||
718 | for (i = 0; i < dma->num_pages; i++) { | 725 | for (i = 0; i < dma->num_pages; i++) { |
719 | /* Each entry needs to be in little endian format. */ | 726 | /* Each entry needs to be in little endian format. */ |
720 | *page_table = dma->pg_map_arr[i] & 0xffffffff; | 727 | *page_table = cpu_to_le32(dma->pg_map_arr[i] & 0xffffffff); |
721 | page_table++; | 728 | page_table++; |
722 | *page_table = (u32) ((u64) dma->pg_map_arr[i] >> 32); | 729 | *page_table = cpu_to_le32((u64) dma->pg_map_arr[i] >> 32); |
723 | page_table++; | 730 | page_table++; |
724 | } | 731 | } |
725 | } | 732 | } |
@@ -2953,7 +2960,8 @@ static void cnic_ulp_stop(struct cnic_dev *dev) | |||
2953 | struct cnic_ulp_ops *ulp_ops; | 2960 | struct cnic_ulp_ops *ulp_ops; |
2954 | 2961 | ||
2955 | mutex_lock(&cnic_lock); | 2962 | mutex_lock(&cnic_lock); |
2956 | ulp_ops = cp->ulp_ops[if_type]; | 2963 | ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type], |
2964 | lockdep_is_held(&cnic_lock)); | ||
2957 | if (!ulp_ops) { | 2965 | if (!ulp_ops) { |
2958 | mutex_unlock(&cnic_lock); | 2966 | mutex_unlock(&cnic_lock); |
2959 | continue; | 2967 | continue; |
@@ -2977,7 +2985,8 @@ static void cnic_ulp_start(struct cnic_dev *dev) | |||
2977 | struct cnic_ulp_ops *ulp_ops; | 2985 | struct cnic_ulp_ops *ulp_ops; |
2978 | 2986 | ||
2979 | mutex_lock(&cnic_lock); | 2987 | mutex_lock(&cnic_lock); |
2980 | ulp_ops = cp->ulp_ops[if_type]; | 2988 | ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type], |
2989 | lockdep_is_held(&cnic_lock)); | ||
2981 | if (!ulp_ops || !ulp_ops->cnic_start) { | 2990 | if (!ulp_ops || !ulp_ops->cnic_start) { |
2982 | mutex_unlock(&cnic_lock); | 2991 | mutex_unlock(&cnic_lock); |
2983 | continue; | 2992 | continue; |
@@ -3041,7 +3050,7 @@ static void cnic_ulp_init(struct cnic_dev *dev) | |||
3041 | struct cnic_ulp_ops *ulp_ops; | 3050 | struct cnic_ulp_ops *ulp_ops; |
3042 | 3051 | ||
3043 | mutex_lock(&cnic_lock); | 3052 | mutex_lock(&cnic_lock); |
3044 | ulp_ops = cnic_ulp_tbl[i]; | 3053 | ulp_ops = cnic_ulp_tbl_prot(i); |
3045 | if (!ulp_ops || !ulp_ops->cnic_init) { | 3054 | if (!ulp_ops || !ulp_ops->cnic_init) { |
3046 | mutex_unlock(&cnic_lock); | 3055 | mutex_unlock(&cnic_lock); |
3047 | continue; | 3056 | continue; |
@@ -3065,7 +3074,7 @@ static void cnic_ulp_exit(struct cnic_dev *dev) | |||
3065 | struct cnic_ulp_ops *ulp_ops; | 3074 | struct cnic_ulp_ops *ulp_ops; |
3066 | 3075 | ||
3067 | mutex_lock(&cnic_lock); | 3076 | mutex_lock(&cnic_lock); |
3068 | ulp_ops = cnic_ulp_tbl[i]; | 3077 | ulp_ops = cnic_ulp_tbl_prot(i); |
3069 | if (!ulp_ops || !ulp_ops->cnic_exit) { | 3078 | if (!ulp_ops || !ulp_ops->cnic_exit) { |
3070 | mutex_unlock(&cnic_lock); | 3079 | mutex_unlock(&cnic_lock); |
3071 | continue; | 3080 | continue; |
@@ -4170,6 +4179,14 @@ static void cnic_enable_bnx2_int(struct cnic_dev *dev) | |||
4170 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx); | 4179 | BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx); |
4171 | } | 4180 | } |
4172 | 4181 | ||
4182 | static void cnic_get_bnx2_iscsi_info(struct cnic_dev *dev) | ||
4183 | { | ||
4184 | u32 max_conn; | ||
4185 | |||
4186 | max_conn = cnic_reg_rd_ind(dev, BNX2_FW_MAX_ISCSI_CONN); | ||
4187 | dev->max_iscsi_conn = max_conn; | ||
4188 | } | ||
4189 | |||
4173 | static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev) | 4190 | static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev) |
4174 | { | 4191 | { |
4175 | struct cnic_local *cp = dev->cnic_priv; | 4192 | struct cnic_local *cp = dev->cnic_priv; |
@@ -4494,6 +4511,8 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev) | |||
4494 | return err; | 4511 | return err; |
4495 | } | 4512 | } |
4496 | 4513 | ||
4514 | cnic_get_bnx2_iscsi_info(dev); | ||
4515 | |||
4497 | return 0; | 4516 | return 0; |
4498 | } | 4517 | } |
4499 | 4518 | ||
@@ -4705,129 +4724,6 @@ static void cnic_init_bnx2x_rx_ring(struct cnic_dev *dev, | |||
4705 | cp->rx_cons = *cp->rx_cons_ptr; | 4724 | cp->rx_cons = *cp->rx_cons_ptr; |
4706 | } | 4725 | } |
4707 | 4726 | ||
4708 | static int cnic_read_bnx2x_iscsi_mac(struct cnic_dev *dev, u32 upper_addr, | ||
4709 | u32 lower_addr) | ||
4710 | { | ||
4711 | u32 val; | ||
4712 | u8 mac[6]; | ||
4713 | |||
4714 | val = CNIC_RD(dev, upper_addr); | ||
4715 | |||
4716 | mac[0] = (u8) (val >> 8); | ||
4717 | mac[1] = (u8) val; | ||
4718 | |||
4719 | val = CNIC_RD(dev, lower_addr); | ||
4720 | |||
4721 | mac[2] = (u8) (val >> 24); | ||
4722 | mac[3] = (u8) (val >> 16); | ||
4723 | mac[4] = (u8) (val >> 8); | ||
4724 | mac[5] = (u8) val; | ||
4725 | |||
4726 | if (is_valid_ether_addr(mac)) { | ||
4727 | memcpy(dev->mac_addr, mac, 6); | ||
4728 | return 0; | ||
4729 | } else { | ||
4730 | return -EINVAL; | ||
4731 | } | ||
4732 | } | ||
4733 | |||
4734 | static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev) | ||
4735 | { | ||
4736 | struct cnic_local *cp = dev->cnic_priv; | ||
4737 | u32 base, base2, addr, addr1, val; | ||
4738 | int port = CNIC_PORT(cp); | ||
4739 | |||
4740 | dev->max_iscsi_conn = 0; | ||
4741 | base = CNIC_RD(dev, MISC_REG_SHARED_MEM_ADDR); | ||
4742 | if (base == 0) | ||
4743 | return; | ||
4744 | |||
4745 | base2 = CNIC_RD(dev, (CNIC_PATH(cp) ? MISC_REG_GENERIC_CR_1 : | ||
4746 | MISC_REG_GENERIC_CR_0)); | ||
4747 | addr = BNX2X_SHMEM_ADDR(base, | ||
4748 | dev_info.port_hw_config[port].iscsi_mac_upper); | ||
4749 | |||
4750 | addr1 = BNX2X_SHMEM_ADDR(base, | ||
4751 | dev_info.port_hw_config[port].iscsi_mac_lower); | ||
4752 | |||
4753 | cnic_read_bnx2x_iscsi_mac(dev, addr, addr1); | ||
4754 | |||
4755 | addr = BNX2X_SHMEM_ADDR(base, validity_map[port]); | ||
4756 | val = CNIC_RD(dev, addr); | ||
4757 | |||
4758 | if (!(val & SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT)) { | ||
4759 | u16 val16; | ||
4760 | |||
4761 | addr = BNX2X_SHMEM_ADDR(base, | ||
4762 | drv_lic_key[port].max_iscsi_init_conn); | ||
4763 | val16 = CNIC_RD16(dev, addr); | ||
4764 | |||
4765 | if (val16) | ||
4766 | val16 ^= 0x1e1e; | ||
4767 | dev->max_iscsi_conn = val16; | ||
4768 | } | ||
4769 | |||
4770 | if (BNX2X_CHIP_IS_E2(cp->chip_id)) | ||
4771 | dev->max_fcoe_conn = BNX2X_FCOE_NUM_CONNECTIONS; | ||
4772 | |||
4773 | if (BNX2X_CHIP_IS_E1H(cp->chip_id) || BNX2X_CHIP_IS_E2(cp->chip_id)) { | ||
4774 | int func = CNIC_FUNC(cp); | ||
4775 | u32 mf_cfg_addr; | ||
4776 | |||
4777 | if (BNX2X_SHMEM2_HAS(base2, mf_cfg_addr)) | ||
4778 | mf_cfg_addr = CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base2, | ||
4779 | mf_cfg_addr)); | ||
4780 | else | ||
4781 | mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET; | ||
4782 | |||
4783 | if (BNX2X_CHIP_IS_E2(cp->chip_id)) { | ||
4784 | /* Must determine if the MF is SD vs SI mode */ | ||
4785 | addr = BNX2X_SHMEM_ADDR(base, | ||
4786 | dev_info.shared_feature_config.config); | ||
4787 | val = CNIC_RD(dev, addr); | ||
4788 | if ((val & SHARED_FEAT_CFG_FORCE_SF_MODE_MASK) == | ||
4789 | SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT) { | ||
4790 | int rc; | ||
4791 | |||
4792 | /* MULTI_FUNCTION_SI mode */ | ||
4793 | addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr, | ||
4794 | func_ext_config[func].func_cfg); | ||
4795 | val = CNIC_RD(dev, addr); | ||
4796 | if (!(val & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD)) | ||
4797 | dev->max_iscsi_conn = 0; | ||
4798 | |||
4799 | if (!(val & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD)) | ||
4800 | dev->max_fcoe_conn = 0; | ||
4801 | |||
4802 | addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr, | ||
4803 | func_ext_config[func]. | ||
4804 | iscsi_mac_addr_upper); | ||
4805 | addr1 = BNX2X_MF_CFG_ADDR(mf_cfg_addr, | ||
4806 | func_ext_config[func]. | ||
4807 | iscsi_mac_addr_lower); | ||
4808 | rc = cnic_read_bnx2x_iscsi_mac(dev, addr, | ||
4809 | addr1); | ||
4810 | if (rc && func > 1) | ||
4811 | dev->max_iscsi_conn = 0; | ||
4812 | |||
4813 | return; | ||
4814 | } | ||
4815 | } | ||
4816 | |||
4817 | addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr, | ||
4818 | func_mf_config[func].e1hov_tag); | ||
4819 | |||
4820 | val = CNIC_RD(dev, addr); | ||
4821 | val &= FUNC_MF_CFG_E1HOV_TAG_MASK; | ||
4822 | if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) { | ||
4823 | dev->max_fcoe_conn = 0; | ||
4824 | dev->max_iscsi_conn = 0; | ||
4825 | } | ||
4826 | } | ||
4827 | if (!is_valid_ether_addr(dev->mac_addr)) | ||
4828 | dev->max_iscsi_conn = 0; | ||
4829 | } | ||
4830 | |||
4831 | static void cnic_init_bnx2x_kcq(struct cnic_dev *dev) | 4727 | static void cnic_init_bnx2x_kcq(struct cnic_dev *dev) |
4832 | { | 4728 | { |
4833 | struct cnic_local *cp = dev->cnic_priv; | 4729 | struct cnic_local *cp = dev->cnic_priv; |
@@ -4909,8 +4805,6 @@ static int cnic_start_bnx2x_hw(struct cnic_dev *dev) | |||
4909 | 4805 | ||
4910 | cnic_init_bnx2x_kcq(dev); | 4806 | cnic_init_bnx2x_kcq(dev); |
4911 | 4807 | ||
4912 | cnic_get_bnx2x_iscsi_info(dev); | ||
4913 | |||
4914 | /* Only 1 EQ */ | 4808 | /* Only 1 EQ */ |
4915 | CNIC_WR16(dev, cp->kcq1.io_addr, MAX_KCQ_IDX); | 4809 | CNIC_WR16(dev, cp->kcq1.io_addr, MAX_KCQ_IDX); |
4916 | CNIC_WR(dev, BAR_CSTRORM_INTMEM + | 4810 | CNIC_WR(dev, BAR_CSTRORM_INTMEM + |
@@ -5343,6 +5237,14 @@ static struct cnic_dev *init_bnx2x_cnic(struct net_device *dev) | |||
5343 | cdev->pcidev = pdev; | 5237 | cdev->pcidev = pdev; |
5344 | cp->chip_id = ethdev->chip_id; | 5238 | cp->chip_id = ethdev->chip_id; |
5345 | 5239 | ||
5240 | if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI)) | ||
5241 | cdev->max_iscsi_conn = ethdev->max_iscsi_conn; | ||
5242 | if (BNX2X_CHIP_IS_E2(cp->chip_id) && | ||
5243 | !(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE)) | ||
5244 | cdev->max_fcoe_conn = ethdev->max_fcoe_conn; | ||
5245 | |||
5246 | memcpy(cdev->mac_addr, ethdev->iscsi_mac, 6); | ||
5247 | |||
5346 | cp->cnic_ops = &cnic_bnx2x_ops; | 5248 | cp->cnic_ops = &cnic_bnx2x_ops; |
5347 | cp->start_hw = cnic_start_bnx2x_hw; | 5249 | cp->start_hw = cnic_start_bnx2x_hw; |
5348 | cp->stop_hw = cnic_stop_bnx2x_hw; | 5250 | cp->stop_hw = cnic_stop_bnx2x_hw; |