|  | @@ -1892,195 +1892,6 @@ static void arbel_poll_eq ( struct ib_device *ibdev ) {
 | 
		
	
		
			
			| 1892 | 1892 |  	}
 | 
		
	
		
			
			| 1893 | 1893 |  }
 | 
		
	
		
			
			| 1894 | 1894 |  
 | 
		
	
		
			
			| 1895 |  | -/***************************************************************************
 | 
		
	
		
			
			| 1896 |  | - *
 | 
		
	
		
			
			| 1897 |  | - * Infiniband link-layer operations
 | 
		
	
		
			
			| 1898 |  | - *
 | 
		
	
		
			
			| 1899 |  | - ***************************************************************************
 | 
		
	
		
			
			| 1900 |  | - */
 | 
		
	
		
			
			| 1901 |  | -
 | 
		
	
		
			
			| 1902 |  | -/**
 | 
		
	
		
			
			| 1903 |  | - * Initialise Infiniband link
 | 
		
	
		
			
			| 1904 |  | - *
 | 
		
	
		
			
			| 1905 |  | - * @v ibdev		Infiniband device
 | 
		
	
		
			
			| 1906 |  | - * @ret rc		Return status code
 | 
		
	
		
			
			| 1907 |  | - */
 | 
		
	
		
			
			| 1908 |  | -static int arbel_open ( struct ib_device *ibdev ) {
 | 
		
	
		
			
			| 1909 |  | -	struct arbel *arbel = ib_get_drvdata ( ibdev );
 | 
		
	
		
			
			| 1910 |  | -	struct arbelprm_init_ib init_ib;
 | 
		
	
		
			
			| 1911 |  | -	int rc;
 | 
		
	
		
			
			| 1912 |  | -
 | 
		
	
		
			
			| 1913 |  | -	memset ( &init_ib, 0, sizeof ( init_ib ) );
 | 
		
	
		
			
			| 1914 |  | -	MLX_FILL_3 ( &init_ib, 0,
 | 
		
	
		
			
			| 1915 |  | -		     mtu_cap, ARBEL_MTU_2048,
 | 
		
	
		
			
			| 1916 |  | -		     port_width_cap, 3,
 | 
		
	
		
			
			| 1917 |  | -		     vl_cap, 1 );
 | 
		
	
		
			
			| 1918 |  | -	MLX_FILL_1 ( &init_ib, 1, max_gid, 1 );
 | 
		
	
		
			
			| 1919 |  | -	MLX_FILL_1 ( &init_ib, 2, max_pkey, 64 );
 | 
		
	
		
			
			| 1920 |  | -	if ( ( rc = arbel_cmd_init_ib ( arbel, ibdev->port,
 | 
		
	
		
			
			| 1921 |  | -					&init_ib ) ) != 0 ) {
 | 
		
	
		
			
			| 1922 |  | -		DBGC ( arbel, "Arbel %p port %d could not intialise IB: %s\n",
 | 
		
	
		
			
			| 1923 |  | -		       arbel, ibdev->port, strerror ( rc ) );
 | 
		
	
		
			
			| 1924 |  | -		return rc;
 | 
		
	
		
			
			| 1925 |  | -	}
 | 
		
	
		
			
			| 1926 |  | -
 | 
		
	
		
			
			| 1927 |  | -	/* Update MAD parameters */
 | 
		
	
		
			
			| 1928 |  | -	ib_smc_update ( ibdev, arbel_mad );
 | 
		
	
		
			
			| 1929 |  | -
 | 
		
	
		
			
			| 1930 |  | -	return 0;
 | 
		
	
		
			
			| 1931 |  | -}
 | 
		
	
		
			
			| 1932 |  | -
 | 
		
	
		
			
			| 1933 |  | -/**
 | 
		
	
		
			
			| 1934 |  | - * Close Infiniband link
 | 
		
	
		
			
			| 1935 |  | - *
 | 
		
	
		
			
			| 1936 |  | - * @v ibdev		Infiniband device
 | 
		
	
		
			
			| 1937 |  | - */
 | 
		
	
		
			
			| 1938 |  | -static void arbel_close ( struct ib_device *ibdev ) {
 | 
		
	
		
			
			| 1939 |  | -	struct arbel *arbel = ib_get_drvdata ( ibdev );
 | 
		
	
		
			
			| 1940 |  | -	int rc;
 | 
		
	
		
			
			| 1941 |  | -
 | 
		
	
		
			
			| 1942 |  | -	if ( ( rc = arbel_cmd_close_ib ( arbel, ibdev->port ) ) != 0 ) {
 | 
		
	
		
			
			| 1943 |  | -		DBGC ( arbel, "Arbel %p port %d could not close IB: %s\n",
 | 
		
	
		
			
			| 1944 |  | -		       arbel, ibdev->port, strerror ( rc ) );
 | 
		
	
		
			
			| 1945 |  | -		/* Nothing we can do about this */
 | 
		
	
		
			
			| 1946 |  | -	}
 | 
		
	
		
			
			| 1947 |  | -}
 | 
		
	
		
			
			| 1948 |  | -
 | 
		
	
		
			
			| 1949 |  | -/**
 | 
		
	
		
			
			| 1950 |  | - * Inform embedded subnet management agent of a received MAD
 | 
		
	
		
			
			| 1951 |  | - *
 | 
		
	
		
			
			| 1952 |  | - * @v ibdev		Infiniband device
 | 
		
	
		
			
			| 1953 |  | - * @v mad		MAD
 | 
		
	
		
			
			| 1954 |  | - * @ret rc		Return status code
 | 
		
	
		
			
			| 1955 |  | - */
 | 
		
	
		
			
			| 1956 |  | -static int arbel_inform_sma ( struct ib_device *ibdev, union ib_mad *mad ) {
 | 
		
	
		
			
			| 1957 |  | -	int rc;
 | 
		
	
		
			
			| 1958 |  | -
 | 
		
	
		
			
			| 1959 |  | -	/* Send the MAD to the embedded SMA */
 | 
		
	
		
			
			| 1960 |  | -	if ( ( rc = arbel_mad ( ibdev, mad ) ) != 0 )
 | 
		
	
		
			
			| 1961 |  | -		return rc;
 | 
		
	
		
			
			| 1962 |  | -
 | 
		
	
		
			
			| 1963 |  | -	/* Update parameters held in software */
 | 
		
	
		
			
			| 1964 |  | -	ib_smc_update ( ibdev, arbel_mad );
 | 
		
	
		
			
			| 1965 |  | -
 | 
		
	
		
			
			| 1966 |  | -	return 0;
 | 
		
	
		
			
			| 1967 |  | -}
 | 
		
	
		
			
			| 1968 |  | -
 | 
		
	
		
			
			| 1969 |  | -/***************************************************************************
 | 
		
	
		
			
			| 1970 |  | - *
 | 
		
	
		
			
			| 1971 |  | - * Multicast group operations
 | 
		
	
		
			
			| 1972 |  | - *
 | 
		
	
		
			
			| 1973 |  | - ***************************************************************************
 | 
		
	
		
			
			| 1974 |  | - */
 | 
		
	
		
			
			| 1975 |  | -
 | 
		
	
		
			
			| 1976 |  | -/**
 | 
		
	
		
			
			| 1977 |  | - * Attach to multicast group
 | 
		
	
		
			
			| 1978 |  | - *
 | 
		
	
		
			
			| 1979 |  | - * @v ibdev		Infiniband device
 | 
		
	
		
			
			| 1980 |  | - * @v qp		Queue pair
 | 
		
	
		
			
			| 1981 |  | - * @v gid		Multicast GID
 | 
		
	
		
			
			| 1982 |  | - * @ret rc		Return status code
 | 
		
	
		
			
			| 1983 |  | - */
 | 
		
	
		
			
			| 1984 |  | -static int arbel_mcast_attach ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 1985 |  | -				struct ib_queue_pair *qp,
 | 
		
	
		
			
			| 1986 |  | -				union ib_gid *gid ) {
 | 
		
	
		
			
			| 1987 |  | -	struct arbel *arbel = ib_get_drvdata ( ibdev );
 | 
		
	
		
			
			| 1988 |  | -	struct arbelprm_mgm_hash hash;
 | 
		
	
		
			
			| 1989 |  | -	struct arbelprm_mgm_entry mgm;
 | 
		
	
		
			
			| 1990 |  | -	unsigned int index;
 | 
		
	
		
			
			| 1991 |  | -	int rc;
 | 
		
	
		
			
			| 1992 |  | -
 | 
		
	
		
			
			| 1993 |  | -	/* Generate hash table index */
 | 
		
	
		
			
			| 1994 |  | -	if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) {
 | 
		
	
		
			
			| 1995 |  | -		DBGC ( arbel, "Arbel %p could not hash GID: %s\n",
 | 
		
	
		
			
			| 1996 |  | -		       arbel, strerror ( rc ) );
 | 
		
	
		
			
			| 1997 |  | -		return rc;
 | 
		
	
		
			
			| 1998 |  | -	}
 | 
		
	
		
			
			| 1999 |  | -	index = MLX_GET ( &hash, hash );
 | 
		
	
		
			
			| 2000 |  | -
 | 
		
	
		
			
			| 2001 |  | -	/* Check for existing hash table entry */
 | 
		
	
		
			
			| 2002 |  | -	if ( ( rc = arbel_cmd_read_mgm ( arbel, index, &mgm ) ) != 0 ) {
 | 
		
	
		
			
			| 2003 |  | -		DBGC ( arbel, "Arbel %p could not read MGM %#x: %s\n",
 | 
		
	
		
			
			| 2004 |  | -		       arbel, index, strerror ( rc ) );
 | 
		
	
		
			
			| 2005 |  | -		return rc;
 | 
		
	
		
			
			| 2006 |  | -	}
 | 
		
	
		
			
			| 2007 |  | -	if ( MLX_GET ( &mgm, mgmqp_0.qi ) != 0 ) {
 | 
		
	
		
			
			| 2008 |  | -		/* FIXME: this implementation allows only a single QP
 | 
		
	
		
			
			| 2009 |  | -		 * per multicast group, and doesn't handle hash
 | 
		
	
		
			
			| 2010 |  | -		 * collisions.  Sufficient for IPoIB but may need to
 | 
		
	
		
			
			| 2011 |  | -		 * be extended in future.
 | 
		
	
		
			
			| 2012 |  | -		 */
 | 
		
	
		
			
			| 2013 |  | -		DBGC ( arbel, "Arbel %p MGID index %#x already in use\n",
 | 
		
	
		
			
			| 2014 |  | -		       arbel, index );
 | 
		
	
		
			
			| 2015 |  | -		return -EBUSY;
 | 
		
	
		
			
			| 2016 |  | -	}
 | 
		
	
		
			
			| 2017 |  | -
 | 
		
	
		
			
			| 2018 |  | -	/* Update hash table entry */
 | 
		
	
		
			
			| 2019 |  | -	MLX_FILL_2 ( &mgm, 8,
 | 
		
	
		
			
			| 2020 |  | -		     mgmqp_0.qpn_i, qp->qpn,
 | 
		
	
		
			
			| 2021 |  | -		     mgmqp_0.qi, 1 );
 | 
		
	
		
			
			| 2022 |  | -	memcpy ( &mgm.u.dwords[4], gid, sizeof ( *gid ) );
 | 
		
	
		
			
			| 2023 |  | -	if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) {
 | 
		
	
		
			
			| 2024 |  | -		DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n",
 | 
		
	
		
			
			| 2025 |  | -		       arbel, index, strerror ( rc ) );
 | 
		
	
		
			
			| 2026 |  | -		return rc;
 | 
		
	
		
			
			| 2027 |  | -	}
 | 
		
	
		
			
			| 2028 |  | -
 | 
		
	
		
			
			| 2029 |  | -	return 0;
 | 
		
	
		
			
			| 2030 |  | -}
 | 
		
	
		
			
			| 2031 |  | -
 | 
		
	
		
			
			| 2032 |  | -/**
 | 
		
	
		
			
			| 2033 |  | - * Detach from multicast group
 | 
		
	
		
			
			| 2034 |  | - *
 | 
		
	
		
			
			| 2035 |  | - * @v ibdev		Infiniband device
 | 
		
	
		
			
			| 2036 |  | - * @v qp		Queue pair
 | 
		
	
		
			
			| 2037 |  | - * @v gid		Multicast GID
 | 
		
	
		
			
			| 2038 |  | - */
 | 
		
	
		
			
			| 2039 |  | -static void arbel_mcast_detach ( struct ib_device *ibdev,
 | 
		
	
		
			
			| 2040 |  | -				 struct ib_queue_pair *qp __unused,
 | 
		
	
		
			
			| 2041 |  | -				 union ib_gid *gid ) {
 | 
		
	
		
			
			| 2042 |  | -	struct arbel *arbel = ib_get_drvdata ( ibdev );
 | 
		
	
		
			
			| 2043 |  | -	struct arbelprm_mgm_hash hash;
 | 
		
	
		
			
			| 2044 |  | -	struct arbelprm_mgm_entry mgm;
 | 
		
	
		
			
			| 2045 |  | -	unsigned int index;
 | 
		
	
		
			
			| 2046 |  | -	int rc;
 | 
		
	
		
			
			| 2047 |  | -
 | 
		
	
		
			
			| 2048 |  | -	/* Generate hash table index */
 | 
		
	
		
			
			| 2049 |  | -	if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) {
 | 
		
	
		
			
			| 2050 |  | -		DBGC ( arbel, "Arbel %p could not hash GID: %s\n",
 | 
		
	
		
			
			| 2051 |  | -		       arbel, strerror ( rc ) );
 | 
		
	
		
			
			| 2052 |  | -		return;
 | 
		
	
		
			
			| 2053 |  | -	}
 | 
		
	
		
			
			| 2054 |  | -	index = MLX_GET ( &hash, hash );
 | 
		
	
		
			
			| 2055 |  | -
 | 
		
	
		
			
			| 2056 |  | -	/* Clear hash table entry */
 | 
		
	
		
			
			| 2057 |  | -	memset ( &mgm, 0, sizeof ( mgm ) );
 | 
		
	
		
			
			| 2058 |  | -	if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) {
 | 
		
	
		
			
			| 2059 |  | -		DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n",
 | 
		
	
		
			
			| 2060 |  | -		       arbel, index, strerror ( rc ) );
 | 
		
	
		
			
			| 2061 |  | -		return;
 | 
		
	
		
			
			| 2062 |  | -	}
 | 
		
	
		
			
			| 2063 |  | -}
 | 
		
	
		
			
			| 2064 |  | -
 | 
		
	
		
			
			| 2065 |  | -/** Arbel Infiniband operations */
 | 
		
	
		
			
			| 2066 |  | -static struct ib_device_operations arbel_ib_operations = {
 | 
		
	
		
			
			| 2067 |  | -	.create_cq	= arbel_create_cq,
 | 
		
	
		
			
			| 2068 |  | -	.destroy_cq	= arbel_destroy_cq,
 | 
		
	
		
			
			| 2069 |  | -	.create_qp	= arbel_create_qp,
 | 
		
	
		
			
			| 2070 |  | -	.modify_qp	= arbel_modify_qp,
 | 
		
	
		
			
			| 2071 |  | -	.destroy_qp	= arbel_destroy_qp,
 | 
		
	
		
			
			| 2072 |  | -	.post_send	= arbel_post_send,
 | 
		
	
		
			
			| 2073 |  | -	.post_recv	= arbel_post_recv,
 | 
		
	
		
			
			| 2074 |  | -	.poll_cq	= arbel_poll_cq,
 | 
		
	
		
			
			| 2075 |  | -	.poll_eq	= arbel_poll_eq,
 | 
		
	
		
			
			| 2076 |  | -	.open		= arbel_open,
 | 
		
	
		
			
			| 2077 |  | -	.close		= arbel_close,
 | 
		
	
		
			
			| 2078 |  | -	.mcast_attach	= arbel_mcast_attach,
 | 
		
	
		
			
			| 2079 |  | -	.mcast_detach	= arbel_mcast_detach,
 | 
		
	
		
			
			| 2080 |  | -	.set_port_info	= arbel_inform_sma,
 | 
		
	
		
			
			| 2081 |  | -	.set_pkey_table	= arbel_inform_sma,
 | 
		
	
		
			
			| 2082 |  | -};
 | 
		
	
		
			
			| 2083 |  | -
 | 
		
	
		
			
			| 2084 | 1895 |  /***************************************************************************
 | 
		
	
		
			
			| 2085 | 1896 |   *
 | 
		
	
		
			
			| 2086 | 1897 |   * Firmware control
 | 
		
	
	
		
			
			|  | @@ -2678,7 +2489,7 @@ static void arbel_free_icm ( struct arbel *arbel ) {
 | 
		
	
		
			
			| 2678 | 2489 |  
 | 
		
	
		
			
			| 2679 | 2490 |  /***************************************************************************
 | 
		
	
		
			
			| 2680 | 2491 |   *
 | 
		
	
		
			
			| 2681 |  | - * PCI interface
 | 
		
	
		
			
			|  | 2492 | + * Initialisation
 | 
		
	
		
			
			| 2682 | 2493 |   *
 | 
		
	
		
			
			| 2683 | 2494 |   ***************************************************************************
 | 
		
	
		
			
			| 2684 | 2495 |   */
 | 
		
	
	
		
			
			|  | @@ -2761,6 +2572,202 @@ static int arbel_configure_special_qps ( struct arbel *arbel ) {
 | 
		
	
		
			
			| 2761 | 2572 |  	return 0;
 | 
		
	
		
			
			| 2762 | 2573 |  }
 | 
		
	
		
			
			| 2763 | 2574 |  
 | 
		
	
		
			
			|  | 2575 | +/***************************************************************************
 | 
		
	
		
			
			|  | 2576 | + *
 | 
		
	
		
			
			|  | 2577 | + * Infiniband link-layer operations
 | 
		
	
		
			
			|  | 2578 | + *
 | 
		
	
		
			
			|  | 2579 | + ***************************************************************************
 | 
		
	
		
			
			|  | 2580 | + */
 | 
		
	
		
			
			|  | 2581 | +
 | 
		
	
		
			
			|  | 2582 | +/**
 | 
		
	
		
			
			|  | 2583 | + * Initialise Infiniband link
 | 
		
	
		
			
			|  | 2584 | + *
 | 
		
	
		
			
			|  | 2585 | + * @v ibdev		Infiniband device
 | 
		
	
		
			
			|  | 2586 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 2587 | + */
 | 
		
	
		
			
			|  | 2588 | +static int arbel_open ( struct ib_device *ibdev ) {
 | 
		
	
		
			
			|  | 2589 | +	struct arbel *arbel = ib_get_drvdata ( ibdev );
 | 
		
	
		
			
			|  | 2590 | +	struct arbelprm_init_ib init_ib;
 | 
		
	
		
			
			|  | 2591 | +	int rc;
 | 
		
	
		
			
			|  | 2592 | +
 | 
		
	
		
			
			|  | 2593 | +	memset ( &init_ib, 0, sizeof ( init_ib ) );
 | 
		
	
		
			
			|  | 2594 | +	MLX_FILL_3 ( &init_ib, 0,
 | 
		
	
		
			
			|  | 2595 | +		     mtu_cap, ARBEL_MTU_2048,
 | 
		
	
		
			
			|  | 2596 | +		     port_width_cap, 3,
 | 
		
	
		
			
			|  | 2597 | +		     vl_cap, 1 );
 | 
		
	
		
			
			|  | 2598 | +	MLX_FILL_1 ( &init_ib, 1, max_gid, 1 );
 | 
		
	
		
			
			|  | 2599 | +	MLX_FILL_1 ( &init_ib, 2, max_pkey, 64 );
 | 
		
	
		
			
			|  | 2600 | +	if ( ( rc = arbel_cmd_init_ib ( arbel, ibdev->port,
 | 
		
	
		
			
			|  | 2601 | +					&init_ib ) ) != 0 ) {
 | 
		
	
		
			
			|  | 2602 | +		DBGC ( arbel, "Arbel %p port %d could not intialise IB: %s\n",
 | 
		
	
		
			
			|  | 2603 | +		       arbel, ibdev->port, strerror ( rc ) );
 | 
		
	
		
			
			|  | 2604 | +		return rc;
 | 
		
	
		
			
			|  | 2605 | +	}
 | 
		
	
		
			
			|  | 2606 | +
 | 
		
	
		
			
			|  | 2607 | +	/* Update MAD parameters */
 | 
		
	
		
			
			|  | 2608 | +	ib_smc_update ( ibdev, arbel_mad );
 | 
		
	
		
			
			|  | 2609 | +
 | 
		
	
		
			
			|  | 2610 | +	return 0;
 | 
		
	
		
			
			|  | 2611 | +}
 | 
		
	
		
			
			|  | 2612 | +
 | 
		
	
		
			
			|  | 2613 | +/**
 | 
		
	
		
			
			|  | 2614 | + * Close Infiniband link
 | 
		
	
		
			
			|  | 2615 | + *
 | 
		
	
		
			
			|  | 2616 | + * @v ibdev		Infiniband device
 | 
		
	
		
			
			|  | 2617 | + */
 | 
		
	
		
			
			|  | 2618 | +static void arbel_close ( struct ib_device *ibdev ) {
 | 
		
	
		
			
			|  | 2619 | +	struct arbel *arbel = ib_get_drvdata ( ibdev );
 | 
		
	
		
			
			|  | 2620 | +	int rc;
 | 
		
	
		
			
			|  | 2621 | +
 | 
		
	
		
			
			|  | 2622 | +	if ( ( rc = arbel_cmd_close_ib ( arbel, ibdev->port ) ) != 0 ) {
 | 
		
	
		
			
			|  | 2623 | +		DBGC ( arbel, "Arbel %p port %d could not close IB: %s\n",
 | 
		
	
		
			
			|  | 2624 | +		       arbel, ibdev->port, strerror ( rc ) );
 | 
		
	
		
			
			|  | 2625 | +		/* Nothing we can do about this */
 | 
		
	
		
			
			|  | 2626 | +	}
 | 
		
	
		
			
			|  | 2627 | +}
 | 
		
	
		
			
			|  | 2628 | +
 | 
		
	
		
			
			|  | 2629 | +/**
 | 
		
	
		
			
			|  | 2630 | + * Inform embedded subnet management agent of a received MAD
 | 
		
	
		
			
			|  | 2631 | + *
 | 
		
	
		
			
			|  | 2632 | + * @v ibdev		Infiniband device
 | 
		
	
		
			
			|  | 2633 | + * @v mad		MAD
 | 
		
	
		
			
			|  | 2634 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 2635 | + */
 | 
		
	
		
			
			|  | 2636 | +static int arbel_inform_sma ( struct ib_device *ibdev, union ib_mad *mad ) {
 | 
		
	
		
			
			|  | 2637 | +	int rc;
 | 
		
	
		
			
			|  | 2638 | +
 | 
		
	
		
			
			|  | 2639 | +	/* Send the MAD to the embedded SMA */
 | 
		
	
		
			
			|  | 2640 | +	if ( ( rc = arbel_mad ( ibdev, mad ) ) != 0 )
 | 
		
	
		
			
			|  | 2641 | +		return rc;
 | 
		
	
		
			
			|  | 2642 | +
 | 
		
	
		
			
			|  | 2643 | +	/* Update parameters held in software */
 | 
		
	
		
			
			|  | 2644 | +	ib_smc_update ( ibdev, arbel_mad );
 | 
		
	
		
			
			|  | 2645 | +
 | 
		
	
		
			
			|  | 2646 | +	return 0;
 | 
		
	
		
			
			|  | 2647 | +}
 | 
		
	
		
			
			|  | 2648 | +
 | 
		
	
		
			
			|  | 2649 | +/***************************************************************************
 | 
		
	
		
			
			|  | 2650 | + *
 | 
		
	
		
			
			|  | 2651 | + * Multicast group operations
 | 
		
	
		
			
			|  | 2652 | + *
 | 
		
	
		
			
			|  | 2653 | + ***************************************************************************
 | 
		
	
		
			
			|  | 2654 | + */
 | 
		
	
		
			
			|  | 2655 | +
 | 
		
	
		
			
			|  | 2656 | +/**
 | 
		
	
		
			
			|  | 2657 | + * Attach to multicast group
 | 
		
	
		
			
			|  | 2658 | + *
 | 
		
	
		
			
			|  | 2659 | + * @v ibdev		Infiniband device
 | 
		
	
		
			
			|  | 2660 | + * @v qp		Queue pair
 | 
		
	
		
			
			|  | 2661 | + * @v gid		Multicast GID
 | 
		
	
		
			
			|  | 2662 | + * @ret rc		Return status code
 | 
		
	
		
			
			|  | 2663 | + */
 | 
		
	
		
			
			|  | 2664 | +static int arbel_mcast_attach ( struct ib_device *ibdev,
 | 
		
	
		
			
			|  | 2665 | +				struct ib_queue_pair *qp,
 | 
		
	
		
			
			|  | 2666 | +				union ib_gid *gid ) {
 | 
		
	
		
			
			|  | 2667 | +	struct arbel *arbel = ib_get_drvdata ( ibdev );
 | 
		
	
		
			
			|  | 2668 | +	struct arbelprm_mgm_hash hash;
 | 
		
	
		
			
			|  | 2669 | +	struct arbelprm_mgm_entry mgm;
 | 
		
	
		
			
			|  | 2670 | +	unsigned int index;
 | 
		
	
		
			
			|  | 2671 | +	int rc;
 | 
		
	
		
			
			|  | 2672 | +
 | 
		
	
		
			
			|  | 2673 | +	/* Generate hash table index */
 | 
		
	
		
			
			|  | 2674 | +	if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) {
 | 
		
	
		
			
			|  | 2675 | +		DBGC ( arbel, "Arbel %p could not hash GID: %s\n",
 | 
		
	
		
			
			|  | 2676 | +		       arbel, strerror ( rc ) );
 | 
		
	
		
			
			|  | 2677 | +		return rc;
 | 
		
	
		
			
			|  | 2678 | +	}
 | 
		
	
		
			
			|  | 2679 | +	index = MLX_GET ( &hash, hash );
 | 
		
	
		
			
			|  | 2680 | +
 | 
		
	
		
			
			|  | 2681 | +	/* Check for existing hash table entry */
 | 
		
	
		
			
			|  | 2682 | +	if ( ( rc = arbel_cmd_read_mgm ( arbel, index, &mgm ) ) != 0 ) {
 | 
		
	
		
			
			|  | 2683 | +		DBGC ( arbel, "Arbel %p could not read MGM %#x: %s\n",
 | 
		
	
		
			
			|  | 2684 | +		       arbel, index, strerror ( rc ) );
 | 
		
	
		
			
			|  | 2685 | +		return rc;
 | 
		
	
		
			
			|  | 2686 | +	}
 | 
		
	
		
			
			|  | 2687 | +	if ( MLX_GET ( &mgm, mgmqp_0.qi ) != 0 ) {
 | 
		
	
		
			
			|  | 2688 | +		/* FIXME: this implementation allows only a single QP
 | 
		
	
		
			
			|  | 2689 | +		 * per multicast group, and doesn't handle hash
 | 
		
	
		
			
			|  | 2690 | +		 * collisions.  Sufficient for IPoIB but may need to
 | 
		
	
		
			
			|  | 2691 | +		 * be extended in future.
 | 
		
	
		
			
			|  | 2692 | +		 */
 | 
		
	
		
			
			|  | 2693 | +		DBGC ( arbel, "Arbel %p MGID index %#x already in use\n",
 | 
		
	
		
			
			|  | 2694 | +		       arbel, index );
 | 
		
	
		
			
			|  | 2695 | +		return -EBUSY;
 | 
		
	
		
			
			|  | 2696 | +	}
 | 
		
	
		
			
			|  | 2697 | +
 | 
		
	
		
			
			|  | 2698 | +	/* Update hash table entry */
 | 
		
	
		
			
			|  | 2699 | +	MLX_FILL_2 ( &mgm, 8,
 | 
		
	
		
			
			|  | 2700 | +		     mgmqp_0.qpn_i, qp->qpn,
 | 
		
	
		
			
			|  | 2701 | +		     mgmqp_0.qi, 1 );
 | 
		
	
		
			
			|  | 2702 | +	memcpy ( &mgm.u.dwords[4], gid, sizeof ( *gid ) );
 | 
		
	
		
			
			|  | 2703 | +	if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) {
 | 
		
	
		
			
			|  | 2704 | +		DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n",
 | 
		
	
		
			
			|  | 2705 | +		       arbel, index, strerror ( rc ) );
 | 
		
	
		
			
			|  | 2706 | +		return rc;
 | 
		
	
		
			
			|  | 2707 | +	}
 | 
		
	
		
			
			|  | 2708 | +
 | 
		
	
		
			
			|  | 2709 | +	return 0;
 | 
		
	
		
			
			|  | 2710 | +}
 | 
		
	
		
			
			|  | 2711 | +
 | 
		
	
		
			
			|  | 2712 | +/**
 | 
		
	
		
			
			|  | 2713 | + * Detach from multicast group
 | 
		
	
		
			
			|  | 2714 | + *
 | 
		
	
		
			
			|  | 2715 | + * @v ibdev		Infiniband device
 | 
		
	
		
			
			|  | 2716 | + * @v qp		Queue pair
 | 
		
	
		
			
			|  | 2717 | + * @v gid		Multicast GID
 | 
		
	
		
			
			|  | 2718 | + */
 | 
		
	
		
			
			|  | 2719 | +static void arbel_mcast_detach ( struct ib_device *ibdev,
 | 
		
	
		
			
			|  | 2720 | +				 struct ib_queue_pair *qp __unused,
 | 
		
	
		
			
			|  | 2721 | +				 union ib_gid *gid ) {
 | 
		
	
		
			
			|  | 2722 | +	struct arbel *arbel = ib_get_drvdata ( ibdev );
 | 
		
	
		
			
			|  | 2723 | +	struct arbelprm_mgm_hash hash;
 | 
		
	
		
			
			|  | 2724 | +	struct arbelprm_mgm_entry mgm;
 | 
		
	
		
			
			|  | 2725 | +	unsigned int index;
 | 
		
	
		
			
			|  | 2726 | +	int rc;
 | 
		
	
		
			
			|  | 2727 | +
 | 
		
	
		
			
			|  | 2728 | +	/* Generate hash table index */
 | 
		
	
		
			
			|  | 2729 | +	if ( ( rc = arbel_cmd_mgid_hash ( arbel, gid, &hash ) ) != 0 ) {
 | 
		
	
		
			
			|  | 2730 | +		DBGC ( arbel, "Arbel %p could not hash GID: %s\n",
 | 
		
	
		
			
			|  | 2731 | +		       arbel, strerror ( rc ) );
 | 
		
	
		
			
			|  | 2732 | +		return;
 | 
		
	
		
			
			|  | 2733 | +	}
 | 
		
	
		
			
			|  | 2734 | +	index = MLX_GET ( &hash, hash );
 | 
		
	
		
			
			|  | 2735 | +
 | 
		
	
		
			
			|  | 2736 | +	/* Clear hash table entry */
 | 
		
	
		
			
			|  | 2737 | +	memset ( &mgm, 0, sizeof ( mgm ) );
 | 
		
	
		
			
			|  | 2738 | +	if ( ( rc = arbel_cmd_write_mgm ( arbel, index, &mgm ) ) != 0 ) {
 | 
		
	
		
			
			|  | 2739 | +		DBGC ( arbel, "Arbel %p could not write MGM %#x: %s\n",
 | 
		
	
		
			
			|  | 2740 | +		       arbel, index, strerror ( rc ) );
 | 
		
	
		
			
			|  | 2741 | +		return;
 | 
		
	
		
			
			|  | 2742 | +	}
 | 
		
	
		
			
			|  | 2743 | +}
 | 
		
	
		
			
			|  | 2744 | +
 | 
		
	
		
			
			|  | 2745 | +/** Arbel Infiniband operations */
 | 
		
	
		
			
			|  | 2746 | +static struct ib_device_operations arbel_ib_operations = {
 | 
		
	
		
			
			|  | 2747 | +	.create_cq	= arbel_create_cq,
 | 
		
	
		
			
			|  | 2748 | +	.destroy_cq	= arbel_destroy_cq,
 | 
		
	
		
			
			|  | 2749 | +	.create_qp	= arbel_create_qp,
 | 
		
	
		
			
			|  | 2750 | +	.modify_qp	= arbel_modify_qp,
 | 
		
	
		
			
			|  | 2751 | +	.destroy_qp	= arbel_destroy_qp,
 | 
		
	
		
			
			|  | 2752 | +	.post_send	= arbel_post_send,
 | 
		
	
		
			
			|  | 2753 | +	.post_recv	= arbel_post_recv,
 | 
		
	
		
			
			|  | 2754 | +	.poll_cq	= arbel_poll_cq,
 | 
		
	
		
			
			|  | 2755 | +	.poll_eq	= arbel_poll_eq,
 | 
		
	
		
			
			|  | 2756 | +	.open		= arbel_open,
 | 
		
	
		
			
			|  | 2757 | +	.close		= arbel_close,
 | 
		
	
		
			
			|  | 2758 | +	.mcast_attach	= arbel_mcast_attach,
 | 
		
	
		
			
			|  | 2759 | +	.mcast_detach	= arbel_mcast_detach,
 | 
		
	
		
			
			|  | 2760 | +	.set_port_info	= arbel_inform_sma,
 | 
		
	
		
			
			|  | 2761 | +	.set_pkey_table	= arbel_inform_sma,
 | 
		
	
		
			
			|  | 2762 | +};
 | 
		
	
		
			
			|  | 2763 | +
 | 
		
	
		
			
			|  | 2764 | +/***************************************************************************
 | 
		
	
		
			
			|  | 2765 | + *
 | 
		
	
		
			
			|  | 2766 | + * PCI interface
 | 
		
	
		
			
			|  | 2767 | + *
 | 
		
	
		
			
			|  | 2768 | + ***************************************************************************
 | 
		
	
		
			
			|  | 2769 | + */
 | 
		
	
		
			
			|  | 2770 | +
 | 
		
	
		
			
			| 2764 | 2771 |  /**
 | 
		
	
		
			
			| 2765 | 2772 |   * Probe PCI device
 | 
		
	
		
			
			| 2766 | 2773 |   *
 |