usr/src/uts/common/io/fibre-channel/fca/qlge/qlge_gld.c
changeset 12073 05ba1c0d6140
parent 11878 ac93462db6d7
equal deleted inserted replaced
12072:2f8174ed4d92 12073:05ba1c0d6140
    18  *
    18  *
    19  * CDDL HEADER END
    19  * CDDL HEADER END
    20  */
    20  */
    21 
    21 
    22 /*
    22 /*
    23  * Copyright 2009 QLogic Corporation. All rights reserved.
    23  * Copyright 2010 QLogic Corporation. All rights reserved.
    24  */
    24  */
    25 
    25 
    26 #include <sys/note.h>
    26 #include <sys/note.h>
    27 #include <qlge.h>
    27 #include <qlge.h>
    28 #include <sys/strsubr.h>
    28 #include <sys/strsubr.h>
    41 static int	ql_m_multicst(void *, boolean_t, const uint8_t *);
    41 static int	ql_m_multicst(void *, boolean_t, const uint8_t *);
    42 static int	ql_m_unicst(void *, const uint8_t *);
    42 static int	ql_m_unicst(void *, const uint8_t *);
    43 static mblk_t	*ql_m_tx(void *, mblk_t *);
    43 static mblk_t	*ql_m_tx(void *, mblk_t *);
    44 static void	ql_m_ioctl(void *, queue_t *, mblk_t *);
    44 static void	ql_m_ioctl(void *, queue_t *, mblk_t *);
    45 static boolean_t ql_m_getcapab(void *, mac_capab_t, void *);
    45 static boolean_t ql_m_getcapab(void *, mac_capab_t, void *);
    46 static int	ql_unicst_set(qlge_t *qlge, const uint8_t *macaddr, int slot);
       
    47 
    46 
    48 static int ql_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
    47 static int ql_m_setprop(void *, const char *, mac_prop_id_t, uint_t,
    49     const void *);
    48     const void *);
    50 static int ql_m_getprop(void *, const char *, mac_prop_id_t, uint_t, void *);
    49 static int ql_m_getprop(void *, const char *, mac_prop_id_t, uint_t, void *);
    51 static void ql_m_propinfo(void *, const char *, mac_prop_id_t,
    50 static void ql_m_propinfo(void *, const char *, mac_prop_id_t,
    72 	ql_m_propinfo
    71 	ql_m_propinfo
    73 };
    72 };
    74 
    73 
    75 char *qlge_priv_prop[] = {
    74 char *qlge_priv_prop[] = {
    76 	"_adv_pause_mode",
    75 	"_adv_pause_mode",
       
    76 	"_fm_enable",
    77 	NULL
    77 	NULL
    78 };
    78 };
    79 
    79 
    80 /*
    80 /*
    81  * This function starts the driver
    81  * This function starts the driver
   164 		    (uint8_t *)ep, 8, ETHERADDRL);
   164 		    (uint8_t *)ep, 8, ETHERADDRL);
   165 		ret = ql_remove_from_multicast_list(qlge, (uint8_t *)ep);
   165 		ret = ql_remove_from_multicast_list(qlge, (uint8_t *)ep);
   166 	}
   166 	}
   167 	mutex_exit(&qlge->gen_mutex);
   167 	mutex_exit(&qlge->gen_mutex);
   168 
   168 
   169 	return ((ret == DDI_SUCCESS) ? 0 : EIO);
   169 	if (ret != DDI_SUCCESS) {
       
   170 		ret = EIO;
       
   171 		if (qlge->fm_enable) {
       
   172 			ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
       
   173 		}
       
   174 	} else {
       
   175 		ret = 0;
       
   176 	}
       
   177 	return (ret);
   170 }
   178 }
   171 
   179 
   172 /*
   180 /*
   173  * Enable or disable promiscuous mode
   181  * Enable or disable promiscuous mode
   174  */
   182  */
   397 }
   405 }
   398 
   406 
   399 /*
   407 /*
   400  * Set the physical network address
   408  * Set the physical network address
   401  */
   409  */
   402 static int
   410 int
   403 ql_unicst_set(qlge_t *qlge, const uint8_t *macaddr, int slot)
   411 ql_unicst_set(qlge_t *qlge, const uint8_t *macaddr, int slot)
   404 {
   412 {
   405 	int status;
   413 	int ret;
   406 
   414 
   407 	status = ql_sem_spinlock(qlge, SEM_MAC_ADDR_MASK);
   415 	ret = ql_sem_spinlock(qlge, SEM_MAC_ADDR_MASK);
   408 	if (status != DDI_SUCCESS)
   416 	if (ret != DDI_SUCCESS)
   409 		return (EIO);
   417 		goto exit;
   410 	status = ql_set_mac_addr_reg(qlge, (uint8_t *)macaddr,
   418 	ret = ql_set_mac_addr_reg(qlge, (uint8_t *)macaddr,
   411 	    MAC_ADDR_TYPE_CAM_MAC,
   419 	    MAC_ADDR_TYPE_CAM_MAC,
   412 	    (uint16_t)(qlge->func_number * MAX_CQ + slot));
   420 	    (uint16_t)(qlge->func_number * MAX_CQ + slot));
   413 	ql_sem_unlock(qlge, SEM_MAC_ADDR_MASK);
   421 	ql_sem_unlock(qlge, SEM_MAC_ADDR_MASK);
   414 
   422 
   415 	return ((status == DDI_SUCCESS) ? 0 : EIO);
   423 exit:
       
   424 	if (ret != DDI_SUCCESS) {
       
   425 		ret = EIO;
       
   426 		if (qlge->fm_enable) {
       
   427 			ddi_fm_service_impact(qlge->dip, DDI_SERVICE_DEGRADED);
       
   428 		}
       
   429 	} else {
       
   430 		ret = 0;
       
   431 	}
       
   432 	return (ret);
   416 }
   433 }
   417 
   434 
   418 /*
   435 /*
   419  * Set default MAC address
   436  * Set default MAC address
   420  * Each function has a total of 128 mac address, function0: 0~127,
   437  * Each function has a total of 128 mac address, function0: 0~127,
   454 	qlge_t *qlge = (qlge_t *)arg;
   471 	qlge_t *qlge = (qlge_t *)arg;
   455 	struct tx_ring *tx_ring;
   472 	struct tx_ring *tx_ring;
   456 	mblk_t *next;
   473 	mblk_t *next;
   457 	int rval;
   474 	int rval;
   458 	uint32_t tx_count = 0;
   475 	uint32_t tx_count = 0;
   459 
   476 	caddr_t bp;
   460 	if (qlge->port_link_state == LS_DOWN) {
   477 	uint8_t selected_ring = 0;
   461 		cmn_err(CE_WARN, "%s(%d): exit due to link down",
   478 
       
   479 	if ((qlge->port_link_state == LS_DOWN) ||
       
   480 	    (qlge->mac_flags != QL_MAC_STARTED)) {
       
   481 
       
   482 		cmn_err(CE_WARN, "!%s(%d): exit due to link down",
   462 		    __func__, qlge->instance);
   483 		    __func__, qlge->instance);
   463 		freemsgchain(mp);
   484 		freemsgchain(mp);
   464 		mp = NULL;
   485 		mp = NULL;
   465 		goto tx_exit;
   486 		goto tx_exit;
   466 	}
   487 	}
   467 
   488 
   468 	/*
   489 	/*
   469 	 * Always send this packet through tx ring 0 for now.
   490 	 * Calculate which tx ring to send this packet
   470 	 * Will use multiple tx rings when Crossbow is supported
       
   471 	 */
   491 	 */
   472 	tx_ring = &qlge->tx_ring[0];
   492 	bp = (caddr_t)mp->b_rptr;
       
   493 	selected_ring = ql_tx_hashing(qlge, bp);
       
   494 	tx_ring = &qlge->tx_ring[selected_ring];
   473 	mutex_enter(&tx_ring->tx_lock);
   495 	mutex_enter(&tx_ring->tx_lock);
   474 	if (tx_ring->mac_flags != QL_MAC_STARTED) {
   496 	if (tx_ring->mac_flags != QL_MAC_STARTED) {
   475 		mutex_exit(&tx_ring->tx_lock);
   497 		mutex_exit(&tx_ring->tx_lock);
   476 		goto tx_exit;
   498 		goto tx_exit;
   477 	}
   499 	}
   682 			err = EINVAL;
   704 			err = EINVAL;
   683 		} else if (qlge->pause != (uint32_t)result) {
   705 		} else if (qlge->pause != (uint32_t)result) {
   684 			qlge->pause = (uint32_t)result;
   706 			qlge->pause = (uint32_t)result;
   685 			if (qlge->flags & INTERRUPTS_ENABLED) {
   707 			if (qlge->flags & INTERRUPTS_ENABLED) {
   686 				mutex_enter(&qlge->mbx_mutex);
   708 				mutex_enter(&qlge->mbx_mutex);
   687 				if (ql_set_port_cfg(qlge) == DDI_FAILURE)
   709 				if (ql_set_pause_mode(qlge) == DDI_FAILURE)
   688 					err = EINVAL;
   710 					err = EINVAL;
   689 				mutex_exit(&qlge->mbx_mutex);
   711 				mutex_exit(&qlge->mbx_mutex);
   690 			}
   712 			}
       
   713 		}
       
   714 		return (err);
       
   715 	} else if (strcmp(pr_name, "_fm_enable") == 0) {
       
   716 		(void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
       
   717 		if ((result != 0) && (result != 1)) {
       
   718 			err = EINVAL;
       
   719 		} else if (qlge->fm_enable != (boolean_t)result) {
       
   720 			qlge->fm_enable = (boolean_t)result;
   691 		}
   721 		}
   692 		return (err);
   722 		return (err);
   693 	}
   723 	}
   694 	return (ENOTSUP);
   724 	return (ENOTSUP);
   695 }
   725 }
   770 	uint32_t value;
   800 	uint32_t value;
   771 
   801 
   772 	if (strcmp(pr_name, "_adv_pause_mode") == 0) {
   802 	if (strcmp(pr_name, "_adv_pause_mode") == 0) {
   773 		value = qlge->pause;
   803 		value = qlge->pause;
   774 		err = 0;
   804 		err = 0;
   775 		goto done;
   805 	} else if (strcmp(pr_name, "_fm_enable") == 0) {
   776 	}
   806 		value = qlge->fm_enable;
   777 
   807 		err = 0;
   778 done:
   808 	}
       
   809 
   779 	if (err == 0) {
   810 	if (err == 0) {
   780 		(void) snprintf(pr_val, pr_valsize, "%d", value);
   811 		(void) snprintf(pr_val, pr_valsize, "%d", value);
   781 	}
   812 	}
   782 	return (err);
   813 	return (err);
   783 }
   814 }
   835 out:
   866 out:
   836 	mutex_exit(&qlge->gen_mutex);
   867 	mutex_exit(&qlge->gen_mutex);
   837 	return (err);
   868 	return (err);
   838 }
   869 }
   839 
   870 
       
   871 /* ARGSUSED */
   840 static void
   872 static void
   841 ql_m_propinfo(void *barg, const char *pr_name, mac_prop_id_t pr_num,
   873 ql_m_propinfo(void *barg, const char *pr_name, mac_prop_id_t pr_num,
   842     mac_prop_info_handle_t prh)
   874     mac_prop_info_handle_t prh)
   843 {
   875 {
   844         _NOTE(ARGUNUSED(barg));
   876 	_NOTE(ARGUNUSED(barg));
   845 
   877 
   846 	switch (pr_num) {
   878 	switch (pr_num) {
   847 	case MAC_PROP_DUPLEX:
   879 	case MAC_PROP_DUPLEX:
   848 	case MAC_PROP_SPEED:
   880 	case MAC_PROP_SPEED:
   849 	case MAC_PROP_STATUS:
   881 	case MAC_PROP_STATUS:
   854 		char val_str[64];
   886 		char val_str[64];
   855 		int default_val;
   887 		int default_val;
   856 
   888 
   857 		if (strcmp(pr_name, "_adv_pause_mode") == 0)
   889 		if (strcmp(pr_name, "_adv_pause_mode") == 0)
   858 			default_val = 2;
   890 			default_val = 2;
       
   891 		else if (strcmp(pr_name, "_fm_enable") == 0)
       
   892 			default_val = 1;
   859 		else
   893 		else
   860 			return;
   894 			return;
   861 
   895 
   862 		(void) snprintf(val_str, sizeof (val_str), "%d", default_val);
   896 		(void) snprintf(val_str, sizeof (val_str), "%d", default_val);
   863 		mac_prop_info_set_default_str(prh, val_str);
   897 		mac_prop_info_set_default_str(prh, val_str);
   894 		break;
   928 		break;
   895 
   929 
   896 	case MAC_CAPAB_LSO: {
   930 	case MAC_CAPAB_LSO: {
   897 		mac_capab_lso_t *cap_lso = (mac_capab_lso_t *)cap_data;
   931 		mac_capab_lso_t *cap_lso = (mac_capab_lso_t *)cap_data;
   898 		uint32_t page_size;
   932 		uint32_t page_size;
       
   933 		uint32_t lso_max;
   899 
   934 
   900 		if ((qlge->cfg_flags & CFG_LSO)&&
   935 		if ((qlge->cfg_flags & CFG_LSO)&&
   901 		    (qlge->cfg_flags & CFG_SUPPORT_SCATTER_GATHER)) {
   936 		    (qlge->cfg_flags & CFG_SUPPORT_SCATTER_GATHER)) {
   902 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
   937 			cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
   903 			page_size = ddi_ptob(qlge->dip, (ulong_t)1);
   938 			page_size = ddi_ptob(qlge->dip, (ulong_t)1);
   904 			cap_lso->lso_basic_tcp_ipv4.lso_max = page_size *
   939 			lso_max = page_size * (QL_MAX_TX_DMA_HANDLES-1);
   905 			    (QL_MAX_TX_DMA_HANDLES-1);
   940 			cap_lso->lso_basic_tcp_ipv4.lso_max =
       
   941 			    min(lso_max, QL_LSO_MAX);
   906 			ret = B_TRUE;
   942 			ret = B_TRUE;
   907 		}
   943 		}
   908 		break;
   944 		break;
   909 	}
   945 	}
   910 
   946