Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34b2aafe authored by Bryan O'Sullivan's avatar Bryan O'Sullivan Committed by Roland Dreier
Browse files

IB/ipath: simplify layering code



A lot of ipath layer code was only called in one place. Now that the
ipath_core and ib_ipath drivers are merged, it's more sensible to simply
inline the simple stuff that the layer code was doing.

Signed-off-by: default avatarBryan O'Sullivan <bryan.osullivan@qlogic.com>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent b1c1b6a3
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@
#include <asm/uaccess.h>

#include "ipath_kernel.h"
#include "ipath_layer.h"
#include "ipath_common.h"

int ipath_diag_inuse;
+188 −87
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@
#include <linux/vmalloc.h>

#include "ipath_kernel.h"
#include "ipath_layer.h"
#include "ipath_verbs.h"
#include "ipath_common.h"

@@ -508,7 +507,6 @@ static int __devinit ipath_init_one(struct pci_dev *pdev,
	ipathfs_add_device(dd);
	ipath_user_add(dd);
	ipath_diag_add(dd);
	ipath_layer_add(dd);
	ipath_register_ib_device(dd);

	goto bail;
@@ -539,7 +537,6 @@ static void __devexit ipath_remove_one(struct pci_dev *pdev)

	dd = pci_get_drvdata(pdev);
	ipath_unregister_ib_device(dd->verbs_dev);
	ipath_layer_remove(dd);
	ipath_diag_remove(dd);
	ipath_user_remove(dd);
	ipathfs_remove_device(dd);
@@ -614,11 +611,12 @@ void ipath_disarm_piobufs(struct ipath_devdata *dd, unsigned first,
 *
 * wait up to msecs milliseconds for IB link state change to occur for
 * now, take the easy polling route.  Currently used only by
 * ipath_layer_set_linkstate.  Returns 0 if state reached, otherwise
 * ipath_set_linkstate.  Returns 0 if state reached, otherwise
 * -ETIMEDOUT state can have multiple states set, for any of several
 * transitions.
 */
int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state, int msecs)
static int ipath_wait_linkstate(struct ipath_devdata *dd, u32 state,
				int msecs)
{
	dd->ipath_sma_state_wanted = state;
	wait_event_interruptible_timeout(ipath_sma_state_wait,
@@ -814,58 +812,6 @@ struct sk_buff *ipath_alloc_skb(struct ipath_devdata *dd,
	return skb;
}

/**
 * ipath_rcv_layer - receive a packet for the layered (ethernet) driver
 * @dd: the infinipath device
 * @etail: the sk_buff number
 * @tlen: the total packet length
 * @hdr: the ethernet header
 *
 * Separate routine for better overall optimization
 */
static void ipath_rcv_layer(struct ipath_devdata *dd, u32 etail,
			    u32 tlen, struct ether_header *hdr)
{
	u32 elen;
	u8 pad, *bthbytes;
	struct sk_buff *skb, *nskb;

	if (dd->ipath_port0_skbs &&
			hdr->sub_opcode == IPATH_ITH4X_OPCODE_ENCAP) {
		/*
		 * Allocate a new sk_buff to replace the one we give
		 * to the network stack.
		 */
		nskb = ipath_alloc_skb(dd, GFP_ATOMIC);
		if (!nskb) {
			/* count OK packets that we drop */
			ipath_stats.sps_krdrops++;
			return;
		}

		bthbytes = (u8 *) hdr->bth;
		pad = (bthbytes[1] >> 4) & 3;
		/* +CRC32 */
		elen = tlen - (sizeof(*hdr) + pad + sizeof(u32));

		skb = dd->ipath_port0_skbs[etail];
		dd->ipath_port0_skbs[etail] = nskb;
		skb_put(skb, elen);

		dd->ipath_f_put_tid(dd, etail + (u64 __iomem *)
				    ((char __iomem *) dd->ipath_kregbase
				     + dd->ipath_rcvegrbase), 0,
				    virt_to_phys(nskb->data));

		__ipath_layer_rcv(dd, hdr, skb);

		/* another ether packet received */
		ipath_stats.sps_ether_rpkts++;
	}
	else if (hdr->sub_opcode == IPATH_ITH4X_OPCODE_LID_ARP)
		__ipath_layer_rcv_lid(dd, hdr);
}

static void ipath_rcv_hdrerr(struct ipath_devdata *dd,
			     u32 eflags,
			     u32 l,
@@ -979,22 +925,17 @@ void ipath_kreceive(struct ipath_devdata *dd)
		if (unlikely(eflags))
			ipath_rcv_hdrerr(dd, eflags, l, etail, rc);
		else if (etype == RCVHQ_RCV_TYPE_NON_KD) {
				ipath_ib_rcv(dd->verbs_dev, rc + 1, ebuf,
					     tlen);
			ipath_ib_rcv(dd->verbs_dev, rc + 1, ebuf, tlen);
			if (dd->ipath_lli_counter)
				dd->ipath_lli_counter--;

		} else if (etype == RCVHQ_RCV_TYPE_EAGER) {
			if (qp == IPATH_KD_QP &&
			    bthbytes[0] == ipath_layer_rcv_opcode &&
			    ebuf)
				ipath_rcv_layer(dd, etail, tlen,
						(struct ether_header *)hdr);
			else
			ipath_cdbg(PKT, "typ %x, opcode %x (eager, "
				   "qp=%x), len %x; ignored\n",
				   etype, bthbytes[0], qp, tlen);
		}
		else if (etype == RCVHQ_RCV_TYPE_EAGER)
			ipath_cdbg(PKT, "typ %x, opcode %x (eager, "
				   "qp=%x), len %x; ignored\n",
				   etype, bthbytes[0], qp, tlen);
		else if (etype == RCVHQ_RCV_TYPE_EXPECTED)
			ipath_dbg("Bug: Expected TID, opcode %x; ignored\n",
				  be32_to_cpu(hdr->bth[0]) & 0xff);
@@ -1320,13 +1261,6 @@ u32 __iomem *ipath_getpiobuf(struct ipath_devdata *dd, u32 * pbufnum)
		goto bail;
	}

	if (updated)
		/*
		 * ran out of bufs, now some (at least this one we just
		 * got) are now available, so tell the layered driver.
		 */
		__ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE);

	/*
	 * set next starting place.  Since it's just an optimization,
	 * it doesn't matter who wins on this, so no locking
@@ -1503,7 +1437,7 @@ int ipath_waitfor_mdio_cmdready(struct ipath_devdata *dd)
	return ret;
}

void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
static void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
{
	static const char *what[4] = {
		[0] = "DOWN",
@@ -1537,6 +1471,180 @@ void ipath_set_ib_lstate(struct ipath_devdata *dd, int which)
			 dd->ipath_ibcctrl | which);
}

int ipath_set_linkstate(struct ipath_devdata *dd, u8 newstate)
{
	u32 lstate;
	int ret;

	switch (newstate) {
	case IPATH_IB_LINKDOWN:
		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_POLL <<
				    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
		/* don't wait */
		ret = 0;
		goto bail;

	case IPATH_IB_LINKDOWN_SLEEP:
		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_SLEEP <<
				    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
		/* don't wait */
		ret = 0;
		goto bail;

	case IPATH_IB_LINKDOWN_DISABLE:
		ipath_set_ib_lstate(dd,
				    INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
				    INFINIPATH_IBCC_LINKINITCMD_SHIFT);
		/* don't wait */
		ret = 0;
		goto bail;

	case IPATH_IB_LINKINIT:
		if (dd->ipath_flags & IPATH_LINKINIT) {
			ret = 0;
			goto bail;
		}
		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_INIT <<
				    INFINIPATH_IBCC_LINKCMD_SHIFT);
		lstate = IPATH_LINKINIT;
		break;

	case IPATH_IB_LINKARM:
		if (dd->ipath_flags & IPATH_LINKARMED) {
			ret = 0;
			goto bail;
		}
		if (!(dd->ipath_flags &
		      (IPATH_LINKINIT | IPATH_LINKACTIVE))) {
			ret = -EINVAL;
			goto bail;
		}
		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ARMED <<
				    INFINIPATH_IBCC_LINKCMD_SHIFT);
		/*
		 * Since the port can transition to ACTIVE by receiving
		 * a non VL 15 packet, wait for either state.
		 */
		lstate = IPATH_LINKARMED | IPATH_LINKACTIVE;
		break;

	case IPATH_IB_LINKACTIVE:
		if (dd->ipath_flags & IPATH_LINKACTIVE) {
			ret = 0;
			goto bail;
		}
		if (!(dd->ipath_flags & IPATH_LINKARMED)) {
			ret = -EINVAL;
			goto bail;
		}
		ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKCMD_ACTIVE <<
				    INFINIPATH_IBCC_LINKCMD_SHIFT);
		lstate = IPATH_LINKACTIVE;
		break;

	default:
		ipath_dbg("Invalid linkstate 0x%x requested\n", newstate);
		ret = -EINVAL;
		goto bail;
	}
	ret = ipath_wait_linkstate(dd, lstate, 2000);

bail:
	return ret;
}

/**
 * ipath_set_mtu - set the MTU
 * @dd: the infinipath device
 * @arg: the new MTU
 *
 * we can handle "any" incoming size, the issue here is whether we
 * need to restrict our outgoing size.   For now, we don't do any
 * sanity checking on this, and we don't deal with what happens to
 * programs that are already running when the size changes.
 * NOTE: changing the MTU will usually cause the IBC to go back to
 * link initialize (IPATH_IBSTATE_INIT) state...
 */
int ipath_set_mtu(struct ipath_devdata *dd, u16 arg)
{
	u32 piosize;
	int changed = 0;
	int ret;

	/*
	 * mtu is IB data payload max.  It's the largest power of 2 less
	 * than piosize (or even larger, since it only really controls the
	 * largest we can receive; we can send the max of the mtu and
	 * piosize).  We check that it's one of the valid IB sizes.
	 */
	if (arg != 256 && arg != 512 && arg != 1024 && arg != 2048 &&
	    arg != 4096) {
		ipath_dbg("Trying to set invalid mtu %u, failing\n", arg);
		ret = -EINVAL;
		goto bail;
	}
	if (dd->ipath_ibmtu == arg) {
		ret = 0;        /* same as current */
		goto bail;
	}

	piosize = dd->ipath_ibmaxlen;
	dd->ipath_ibmtu = arg;

	if (arg >= (piosize - IPATH_PIO_MAXIBHDR)) {
		/* Only if it's not the initial value (or reset to it) */
		if (piosize != dd->ipath_init_ibmaxlen) {
			dd->ipath_ibmaxlen = piosize;
			changed = 1;
		}
	} else if ((arg + IPATH_PIO_MAXIBHDR) != dd->ipath_ibmaxlen) {
		piosize = arg + IPATH_PIO_MAXIBHDR;
		ipath_cdbg(VERBOSE, "ibmaxlen was 0x%x, setting to 0x%x "
			   "(mtu 0x%x)\n", dd->ipath_ibmaxlen, piosize,
			   arg);
		dd->ipath_ibmaxlen = piosize;
		changed = 1;
	}

	if (changed) {
		/*
		 * set the IBC maxpktlength to the size of our pio
		 * buffers in words
		 */
		u64 ibc = dd->ipath_ibcctrl;
		ibc &= ~(INFINIPATH_IBCC_MAXPKTLEN_MASK <<
			 INFINIPATH_IBCC_MAXPKTLEN_SHIFT);

		piosize = piosize - 2 * sizeof(u32);    /* ignore pbc */
		dd->ipath_ibmaxlen = piosize;
		piosize /= sizeof(u32); /* in words */
		/*
		 * for ICRC, which we only send in diag test pkt mode, and
		 * we don't need to worry about that for mtu
		 */
		piosize += 1;

		ibc |= piosize << INFINIPATH_IBCC_MAXPKTLEN_SHIFT;
		dd->ipath_ibcctrl = ibc;
		ipath_write_kreg(dd, dd->ipath_kregs->kr_ibcctrl,
				 dd->ipath_ibcctrl);
		dd->ipath_f_tidtemplate(dd);
	}

	ret = 0;

bail:
	return ret;
}

int ipath_set_lid(struct ipath_devdata *dd, u32 arg, u8 lmc)
{
	dd->ipath_lid = arg;
	dd->ipath_lmc = lmc;

	return 0;
}

/**
 * ipath_read_kreg64_port - read a device's per-port 64-bit kernel register
 * @dd: the infinipath device
@@ -1640,13 +1748,6 @@ void ipath_shutdown_device(struct ipath_devdata *dd)
	ipath_set_ib_lstate(dd, INFINIPATH_IBCC_LINKINITCMD_DISABLE <<
			    INFINIPATH_IBCC_LINKINITCMD_SHIFT);

	/*
	 * we are shutting down, so tell the layered driver.  We don't do
	 * this on just a link state change, much like ethernet, a cable
	 * unplug, etc. doesn't change driver state
	 */
	ipath_layer_intr(dd, IPATH_LAYER_INT_IF_DOWN);

	/* disable IBC */
	dd->ipath_control &= ~INFINIPATH_C_LINKENABLE;
	ipath_write_kreg(dd, dd->ipath_kregs->kr_control,
+0 −1
Original line number Diff line number Diff line
@@ -39,7 +39,6 @@
#include <asm/pgtable.h>

#include "ipath_kernel.h"
#include "ipath_layer.h"
#include "ipath_common.h"

static int ipath_open(struct inode *, struct file *);
+0 −7
Original line number Diff line number Diff line
@@ -34,7 +34,6 @@
#include <linux/pci.h>

#include "ipath_kernel.h"
#include "ipath_layer.h"
#include "ipath_verbs.h"
#include "ipath_common.h"

@@ -290,8 +289,6 @@ static void handle_e_ibstatuschanged(struct ipath_devdata *dd,
		*dd->ipath_statusp |=
			IPATH_STATUS_IB_READY | IPATH_STATUS_IB_CONF;
		dd->ipath_f_setextled(dd, lstate, ltstate);

		__ipath_layer_intr(dd, IPATH_LAYER_INT_IF_UP);
	} else if ((val & IPATH_IBSTATE_MASK) == IPATH_IBSTATE_INIT) {
		/*
		 * set INIT and DOWN.  Down is checked by most of the other
@@ -709,10 +706,6 @@ static void handle_layer_pioavail(struct ipath_devdata *dd)
{
	int ret;

	ret = __ipath_layer_intr(dd, IPATH_LAYER_INT_SEND_CONTINUE);
	if (ret > 0)
		goto set;

	ret = ipath_ib_piobufavail(dd->verbs_dev);
	if (ret > 0)
		goto set;
+3 −12
Original line number Diff line number Diff line
@@ -518,16 +518,6 @@ extern struct list_head ipath_dev_list;
extern spinlock_t ipath_devs_lock;
extern struct ipath_devdata *ipath_lookup(int unit);

extern u16 ipath_layer_rcv_opcode;
extern int __ipath_layer_intr(struct ipath_devdata *, u32);
extern int ipath_layer_intr(struct ipath_devdata *, u32);
extern int __ipath_layer_rcv(struct ipath_devdata *, void *,
			     struct sk_buff *);
extern int __ipath_layer_rcv_lid(struct ipath_devdata *, void *);

void ipath_layer_add(struct ipath_devdata *);
void ipath_layer_remove(struct ipath_devdata *);

int ipath_init_chip(struct ipath_devdata *, int);
int ipath_enable_wc(struct ipath_devdata *dd);
void ipath_disable_wc(struct ipath_devdata *dd);
@@ -575,12 +565,13 @@ void ipath_free_pddata(struct ipath_devdata *, struct ipath_portdata *);

int ipath_parse_ushort(const char *str, unsigned short *valp);

int ipath_wait_linkstate(struct ipath_devdata *, u32, int);
void ipath_set_ib_lstate(struct ipath_devdata *, int);
void ipath_kreceive(struct ipath_devdata *);
int ipath_setrcvhdrsize(struct ipath_devdata *, unsigned);
int ipath_reset_device(int);
void ipath_get_faststats(unsigned long);
int ipath_set_linkstate(struct ipath_devdata *, u8);
int ipath_set_mtu(struct ipath_devdata *, u16);
int ipath_set_lid(struct ipath_devdata *, u32, u8);

/* for use in system calls, where we want to know device type, etc. */
#define port_fp(fp) ((struct ipath_portdata *) (fp)->private_data)
Loading