modified interrupt handler for riffa linux driver using ptr_ring
112 líneas
struct item item_recv_push_EVENT_SG_BUF_READ = {EVENT_SG_BUF_READ, 0};
struct item item_recv_push_EVENT_TXN_DONE = {EVENT_TXN_DONE, 0};
struct item item_recv_push_EVENT_TXN_OFFLAST = {EVENT_TXN_OFFLAST, 0};
struct item item_send_push_EVENT_SG_BUF_READ = {EVENT_SG_BUF_READ, 0};
struct item item_send_push_EVENT_TXN_DONE = {EVENT_TXN_DONE, 0};
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
// INTERRUPT HANDLER
// INTERRUPT HANDLER
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
/**
/**
 * Reads the interrupt vector and processes it. If processing VECT0, off will
 * Reads the interrupt vector and processes it. If processing VECT0, off will
 * be 0. If processing VECT1, off will be 6.
 * be 0. If processing VECT1, off will be 6.
 */
 */
static inline void process_intr_vector(struct fpga_state * sc, int off, 
static inline void process_intr_vector(struct fpga_state * sc, int off, 
				unsigned int vect)
				unsigned int vect)
{
{
	// VECT_0/VECT_1 are organized from right to left (LSB to MSB) as:
	// VECT_0/VECT_1 are organized from right to left (LSB to MSB) as:
	// [ 0] TX_TXN			for channel 0 in VECT_0, channel 6 in VECT_1
	// [ 0] TX_TXN			for channel 0 in VECT_0, channel 6 in VECT_1
	// [ 1] TX_SG_BUF_RECVD	for channel 0 in VECT_0, channel 6 in VECT_1
	// [ 1] TX_SG_BUF_RECVD	for channel 0 in VECT_0, channel 6 in VECT_1
	// [ 2] TX_TXN_DONE		for channel 0 in VECT_0, channel 6 in VECT_1
	// [ 2] TX_TXN_DONE		for channel 0 in VECT_0, channel 6 in VECT_1
	// [ 3] RX_SG_BUF_RECVD	for channel 0 in VECT_0, channel 6 in VECT_1
	// [ 3] RX_SG_BUF_RECVD	for channel 0 in VECT_0, channel 6 in VECT_1
	// [ 4] RX_TXN_DONE		for channel 0 in VECT_0, channel 6 in VECT_1
	// [ 4] RX_TXN_DONE		for channel 0 in VECT_0, channel 6 in VECT_1
	// ...
	// ...
	// [25] TX_TXN			for channel 5 in VECT_0, channel 11 in VECT_1
	// [25] TX_TXN			for channel 5 in VECT_0, channel 11 in VECT_1
	// [26] TX_SG_BUF_RECVD	for channel 5 in VECT_0, channel 11 in VECT_1
	// [26] TX_SG_BUF_RECVD	for channel 5 in VECT_0, channel 11 in VECT_1
	// [27] TX_TXN_DONE		for channel 5 in VECT_0, channel 11 in VECT_1
	// [27] TX_TXN_DONE		for channel 5 in VECT_0, channel 11 in VECT_1
	// [28] RX_SG_BUF_RECVD	for channel 5 in VECT_0, channel 11 in VECT_1
	// [28] RX_SG_BUF_RECVD	for channel 5 in VECT_0, channel 11 in VECT_1
	// [29] RX_TXN_DONE		for channel 5 in VECT_0, channel 11 in VECT_1
	// [29] RX_TXN_DONE		for channel 5 in VECT_0, channel 11 in VECT_1
	// Positions 30 - 31 in both VECT_0 and VECT_1 are zero.
	// Positions 30 - 31 in both VECT_0 and VECT_1 are zero.
	unsigned int offlast;
	unsigned int offlast;
	unsigned int len;
	unsigned int len;
	int recv;
	int recv;
	int send;
	int send;
	int chnl;
	int chnl;
	int i;
	int i;
	offlast = 0;
	len = 0;
//printk(KERN_INFO "riffa: intrpt_handler received:%08x\n", vect);
//printk(KERN_INFO "riffa: intrpt_handler received:%08x\n", vect);
	if (vect & 0xC0000000) {
	if (vect & 0xC0000000) {
		printk(KERN_ERR "riffa: fpga:%d, received bad interrupt vector:%08x\n", sc->id, vect);
		printk(KERN_ERR "riffa: fpga:%d, received bad interrupt vector:%08x\n", sc->id, vect);
		return;
		return;
	}
	}
	for (i = 0; i < 6 && (i+off) < sc->num_chnls; ++i) {
	for (i = 0; i < 6 && (i+off) < sc->num_chnls; ++i) {
		chnl = i + off;
		chnl = i + off;
		recv = 0; 
		recv = 0; 
		send = 0; 
		send = 0; 
		// TX (PC receive) scatter gather buffer is read.
		// TX (PC receive) scatter gather buffer is read.
		if (vect & (1<<((5*i)+1))) { 
		if (vect & (1<<((5*i)+1))) { 
			recv = 1; 
			recv = 1; 
			// Keep track so the thread can handle this.
			// Keep track so the thread can handle this.
			if (push_circ_queue(sc->recv[chnl]->msgs, EVENT_SG_BUF_READ, 0)) {
			if (ptr_ring_produce_any(sc->recv[chnl]->msgs, &item_recv_push_EVENT_SG_BUF_READ)) {
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv sg buf read msg queue full\n", sc->id, chnl);
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv sg buf read msg queue full\n", sc->id, chnl);
			}
			}
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv sg buf read\n", sc->id, chnl);
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv sg buf read\n", sc->id, chnl);
		}
		}
		// TX (PC receive) transaction done.
		// TX (PC receive) transaction done.
		if (vect & (1<<((5*i)+2))) { 
		if (vect & (1<<((5*i)+2))) { 
			recv = 1; 
			recv = 1; 
			// Read the transferred amount.
			// Read the transferred amount.
			len = read_reg(sc, CHNL_REG(chnl, TX_TNFR_LEN_REG_OFF));
			len = read_reg(sc, CHNL_REG(chnl, TX_TNFR_LEN_REG_OFF));
			item_recv_push_EVENT_TXN_DONE.val2 = len;
			// Notify the thread.
			// Notify the thread.
			if (push_circ_queue(sc->recv[chnl]->msgs, EVENT_TXN_DONE, len)) {
			if (ptr_ring_produce_any(sc->recv[chnl]->msgs, &item_recv_push_EVENT_TXN_DONE)) {
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv txn done msg queue full\n", sc->id, chnl);
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv txn done msg queue full\n", sc->id, chnl);
			}
			}
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv txn done\n", sc->id, chnl);
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv txn done\n", sc->id, chnl);
		}
		}
		// New TX (PC receive) transaction.
		// New TX (PC receive) transaction.
		if (vect & (1<<((5*i)+0))) { 
		if (vect & (1<<((5*i)+0))) { 
			recv = 1; 
			recv = 1; 
			recv_sg_buf_populated = 0; // resets for new transaction
			recv_sg_buf_populated = 0; // resets for new transaction
			// Read the offset/last and length
			// Read the offset/last and length
			offlast = read_reg(sc, CHNL_REG(chnl, TX_OFFLAST_REG_OFF));
			offlast = read_reg(sc, CHNL_REG(chnl, TX_OFFLAST_REG_OFF));
			tx_len = read_reg(sc, CHNL_REG(chnl, TX_LEN_REG_OFF));
			tx_len = read_reg(sc, CHNL_REG(chnl, TX_LEN_REG_OFF));
			item_recv_push_EVENT_TXN_OFFLAST.val2 = offlast;
			// Keep track of this transaction
			// Keep track of this transaction
			if (push_circ_queue(sc->recv[chnl]->msgs, EVENT_TXN_OFFLAST, offlast)) {
			if (ptr_ring_produce_any(sc->recv[chnl]->msgs, &item_recv_push_EVENT_TXN_OFFLAST)) {
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv txn offlast msg queue full\n", sc->id, chnl);
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv txn offlast msg queue full\n", sc->id, chnl);
			}
			}
			/*if (push_circ_queue(sc->recv[chnl]->msgs, EVENT_TXN_LEN, len)) {
			/*if (push_circ_queue(sc->recv[chnl]->msgs, EVENT_TXN_LEN, len)) {
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv txn len msg queue full\n", sc->id, chnl);
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, recv txn len msg queue full\n", sc->id, chnl);
			}*/
			}*/
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv txn (len:%d off:%d last:%d)\n", sc->id, chnl, tx_len, (offlast>>1), (offlast & 0x1));
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, recv txn (len:%d off:%d last:%d)\n", sc->id, chnl, tx_len, (offlast>>1), (offlast & 0x1));
		}
		}
		// RX (PC send) scatter gather buffer is read.
		// RX (PC send) scatter gather buffer is read.
		if (vect & (1<<((5*i)+3))) { 
		if (vect & (1<<((5*i)+3))) { 
			send = 1; 
			send = 1; 
			// Keep track so the thread can handle this.
			// Keep track so the thread can handle this.
			if (push_circ_queue(sc->send[chnl]->msgs, EVENT_SG_BUF_READ, 0)) {
			if (ptr_ring_produce_any(sc->send[chnl]->msgs, &item_send_push_EVENT_SG_BUF_READ)) {
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, send sg buf read msg queue full\n", sc->id, chnl);
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, send sg buf read msg queue full\n", sc->id, chnl);
			}
			}
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, send sg buf read\n", sc->id, chnl);
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, send sg buf read\n", sc->id, chnl);
		}
		}
		// RX (PC send) transaction done.
		// RX (PC send) transaction done.
		if (vect & (1<<((5*i)+4))) {
		if (vect & (1<<((5*i)+4))) {
			send = 1; 
			send = 1; 
			// Read the transferred amount.
			// Read the transferred amount.
			len = read_reg(sc, CHNL_REG(chnl, RX_TNFR_LEN_REG_OFF));
			len = read_reg(sc, CHNL_REG(chnl, RX_TNFR_LEN_REG_OFF));
			item_send_push_EVENT_TXN_DONE.val2 = len;
			// Notify the thread.
			// Notify the thread.
			if (push_circ_queue(sc->send[chnl]->msgs, EVENT_TXN_DONE, len)) {
			if (ptr_ring_produce_any(sc->send[chnl]->msgs, &item_send_push_EVENT_TXN_DONE)) {
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, send txn done msg queue full\n", sc->id, chnl);
				printk(KERN_ERR "riffa: fpga:%d chnl:%d, send txn done msg queue full\n", sc->id, chnl);
			}
			}
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, send txn done\n", sc->id, chnl);
			DEBUG_MSG(KERN_INFO "riffa: fpga:%d chnl:%d, send txn done\n", sc->id, chnl);
		}
		}
		// Wake up the thread?
		// Wake up the thread?
		if (recv)
		if (recv)
			wake_up(&sc->recv[chnl]->waitq);
			wake_up(&sc->recv[chnl]->waitq);
		if (send)
		if (send)
			wake_up(&sc->send[chnl]->waitq);
			wake_up(&sc->send[chnl]->waitq);
	}
	}
}
}