Example #1
0
void t3_update_master_devs(struct toedev *tdev)
{
	int i;

	for (i = 0; i < tdev->nlldev; i++) {
		struct net_device *dev = tdev->lldev[i];

		if (dev->flags & IFF_SLAVE) {
			struct net_device *bond_dev = dev->master;
			struct bonding *bond = (struct bonding *)netdev_priv(bond_dev);
			struct toedev *slave_tdev = NULL;
			struct slave *slave;
			int i, ofld_cnt = 0;

			if (netdev_is_offload(bond_dev))
				continue;

			read_lock_bh(&bond->lock);
			bond_for_each_slave(bond, slave, i) {
				ofld_cnt += !!netdev_is_offload(slave->dev);

				if (!slave_tdev)
					slave_tdev = TOEDEV(slave->dev);
				else if (slave_tdev != TOEDEV(slave->dev)) {
					slave_tdev = NULL;
					break;
				}
			}
			read_unlock_bh(&bond->lock);

			if (ofld_cnt == bond->slave_cnt && slave_tdev)
				netdev_set_offload(bond_dev);
		}
	}
Example #2
0
/*
 * Provide an opportunity for a TOE driver to offload.
 */
int
tcp_offload_connect(struct socket *so, struct sockaddr *nam)
{
	struct ifnet *ifp;
	struct toedev *tod;
	struct rtentry *rt;
	int error = EOPNOTSUPP;

	INP_WLOCK_ASSERT(sotoinpcb(so));
	KASSERT(nam->sa_family == AF_INET || nam->sa_family == AF_INET6,
	    ("%s: called with sa_family %d", __func__, nam->sa_family));

	if (registered_toedevs == 0)
		return (error);

	rt = rtalloc1(nam, 0, 0);
	if (rt)
		RT_UNLOCK(rt);
	else
		return (EHOSTUNREACH);

	ifp = rt->rt_ifp;

	if (nam->sa_family == AF_INET && !(ifp->if_capenable & IFCAP_TOE4))
		goto done;
	if (nam->sa_family == AF_INET6 && !(ifp->if_capenable & IFCAP_TOE6))
		goto done;

	tod = TOEDEV(ifp);
	if (tod != NULL)
		error = tod->tod_connect(tod, so, rt, nam);
done:
	RTFREE(rt);
	return (error);
}
Example #3
0
static inline int lookup_port(struct net_device *slave_dev)
{
	int i, port = -1;
	struct toedev *tdev = TOEDEV(slave_dev);
	struct adap_ports *port_info = TOM_DATA(tdev)->ports;

	for (i = 0; i < port_info->nports; i++) {
		if (slave_dev != port_info->lldevs[i])
			continue;

		port = i;
		break;
	}
	return port;
}
Example #4
0
int
tcp_offload_connect(struct socket *so, struct sockaddr *nam)
{
	struct ifnet *ifp;
	struct toedev *tdev;
	struct rtentry *rt;
	int error;

	if (toedev_registration_count == 0)
		return (EINVAL);
	
	/*
	 * Look up the route used for the connection to 
	 * determine if it uses an interface capable of
	 * offloading the connection.
	 */
	rt = rtalloc1(nam, 0 /*report*/, 0 /*ignflags*/);
	if (rt) 
		RT_UNLOCK(rt);
	else 
		return (EHOSTUNREACH);

	ifp = rt->rt_ifp;
	if ((ifp->if_capenable & IFCAP_TOE) == 0) {
		error = EINVAL;
		goto fail;
	}
	
	tdev = TOEDEV(ifp);
	if (tdev == NULL) {
		error = EPERM;
		goto fail;
	}
	
	if (tdev->tod_can_offload(tdev, so) == 0) {
		error = EPERM;
		goto fail;
	}
	
	return (tdev->tod_connect(tdev, so, rt, nam));
fail:
	RTFREE(rt);
	return (error);
}
Example #5
0
/*
 * Ground control to Major TOM
 * Commencing countdown, engines on
 */
static int
t3_tom_activate(struct adapter *sc)
{
	struct tom_data *td;
	struct toedev *tod;
	int i, rc = 0;
	struct mc5_params *mc5 = &sc->params.mc5;
	u_int ntids, natids, mtus;

	ADAPTER_LOCK_ASSERT_OWNED(sc);	/* for sc->flags */

	/* per-adapter softc for TOM */
	td = malloc(sizeof(*td), M_CXGB, M_ZERO | M_NOWAIT);
	if (td == NULL)
		return (ENOMEM);

	/* List of TOE PCBs and associated lock */
	mtx_init(&td->toep_list_lock, "PCB list lock", NULL, MTX_DEF);
	TAILQ_INIT(&td->toep_list);

	/* Listen context */
	mtx_init(&td->lctx_hash_lock, "lctx hash lock", NULL, MTX_DEF);
	td->listen_hash = hashinit_flags(LISTEN_HASH_SIZE, M_CXGB,
	    &td->listen_mask, HASH_NOWAIT);

	/* TID release task */
	TASK_INIT(&td->tid_release_task, 0 , t3_process_tid_release_list, td);
	mtx_init(&td->tid_release_lock, "tid release", NULL, MTX_DEF);

	/* L2 table */
	td->l2t = t3_init_l2t(L2T_SIZE);
	if (td->l2t == NULL) {
		rc = ENOMEM;
		goto done;
	}

	/* TID tables */
	ntids = t3_mc5_size(&sc->mc5) - mc5->nroutes - mc5->nfilters -
	    mc5->nservers;
	natids = min(ntids / 2, 64 * 1024);
	rc = alloc_tid_tabs(&td->tid_maps, ntids, natids, mc5->nservers,
	    0x100000 /* ATID_BASE */, ntids);
	if (rc != 0)
		goto done;

	/* CPL handlers */
	t3_init_listen_cpl_handlers(sc);
	t3_init_l2t_cpl_handlers(sc);
	t3_init_cpl_io(sc);

	/* toedev ops */
	tod = &td->tod;
	init_toedev(tod);
	tod->tod_softc = sc;
	tod->tod_connect = t3_connect;
	tod->tod_listen_start = t3_listen_start;
	tod->tod_listen_stop = t3_listen_stop;
	tod->tod_rcvd = t3_rcvd;
	tod->tod_output = t3_tod_output;
	tod->tod_send_rst = t3_send_rst;
	tod->tod_send_fin = t3_send_fin;
	tod->tod_pcb_detach = t3_pcb_detach;
	tod->tod_l2_update = t3_l2_update;
	tod->tod_syncache_added = t3_syncache_added;
	tod->tod_syncache_removed = t3_syncache_removed;
	tod->tod_syncache_respond = t3_syncache_respond;
	tod->tod_offload_socket = t3_offload_socket;

	/* port MTUs */
	mtus = sc->port[0].ifp->if_mtu;
	if (sc->params.nports > 1)
		mtus |= sc->port[1].ifp->if_mtu << 16;
	t3_write_reg(sc, A_TP_MTU_PORT_TABLE, mtus);
	t3_load_mtus(sc, sc->params.mtus, sc->params.a_wnd, sc->params.b_wnd,
	    sc->params.rev == 0 ? sc->port[0].ifp->if_mtu : 0xffff);

	/* SMT entry for each port */
	for_each_port(sc, i) {
		write_smt_entry(sc, i);
		TOEDEV(sc->port[i].ifp) = &td->tod;
	}
Example #6
0
/*
 * Allocate a TOM data structure,
 * initialize its cpl_handlers
 * and register it as a T3C client
 */
static void
t3c_tom_add(struct t3cdev *cdev)
{
	int i;
	unsigned int wr_len;
	struct tom_data *t;
	struct toedev *tdev;
	struct adap_ports *port_info;

	t = malloc(sizeof(*t), M_CXGB, M_NOWAIT|M_ZERO);
	if (t == NULL)
		return;

	cdev->send = t3_offload_tx;
	cdev->ctl = cxgb_offload_ctl;
	
	if (cdev->ctl(cdev, GET_WR_LEN, &wr_len) < 0)
		goto out_free_tom;

	port_info = malloc(sizeof(*port_info), M_CXGB, M_NOWAIT|M_ZERO);
	if (!port_info)
		goto out_free_tom;

	if (cdev->ctl(cdev, GET_PORTS, port_info) < 0)
		goto out_free_all;

	t3_init_wr_tab(wr_len);
	t->cdev = cdev;
	t->client = &t3c_tom_client;

	/* Register TCP offload device */
	tdev = &t->tdev;
	tdev->tod_ttid = cdev2type(cdev);
	tdev->tod_lldev = cdev->lldev;
	
	if (register_toedev(tdev, "toe%d")) {
		printf("unable to register offload device");
		goto out_free_all;
	}
	TOM_DATA(tdev) = t;

	for (i = 0; i < port_info->nports; i++) {
		struct ifnet *ifp = port_info->lldevs[i];
		TOEDEV(ifp) = tdev;

		CTR1(KTR_TOM, "enabling toe on %p", ifp);
		ifp->if_capabilities |= IFCAP_TOE4;
		ifp->if_capenable |= IFCAP_TOE4;
	}
	t->ports = port_info;

	/* Add device to the list of offload devices */
	t3cdev_add(t);

	/* Activate TCP offload device */
	cxgb_offload_activate(TOM_DATA(tdev)->cdev->adapter);

	activate_offload(tdev);
	cxgb_register_listeners();
	return;

out_free_all:
	printf("out_free_all fail\n");
	free(port_info, M_CXGB);
out_free_tom:
	printf("out_free_tom fail\n");
	free(t, M_CXGB);
	return;
}