diff --git a/drivers/net/mmnif.c b/drivers/net/mmnif.c index c368bce1..0e3d8bac 100644 --- a/drivers/net/mmnif.c +++ b/drivers/net/mmnif.c @@ -59,6 +59,8 @@ extern HANDLE hProc; #define MMNIF_CORES 2 +#define MMNIF_WORKER_BUDGET 5 + /* decide whether it's polling mode or not */ static int no_irq = 0; @@ -86,10 +88,24 @@ unsigned int mpb_size = NULL; /* Register offset for the CONFIG and LOCK registers */ +#define RCK_GLCFG0 0x10 +#define RCK_GLCFG1 0x18 #define RCK_TILEID 0x100 +#define RCK_TILE_SIZE 0x01000000 + /* Start address of the local register bank */ static int local_crb = 0xF8000000; +static int crb = 0xE0000000; + +/* just set and reset the irq */ +static int pulse_irq = 1; + +/* Mask of the interrupt bits */ +#define RCK_INTR_MASK 0x00000002 +#define RCK_NMI_MASK 0x00000001 + + /* * the memory mapped network device @@ -111,11 +127,21 @@ typedef struct mmnif_device_stats unsigned int rx_err; unsigned int rx; - unsigned int rx_intr; - unsigned int rx_poll; + unsigned int rx_bytes; unsigned int tx_err; unsigned int tx; + + unsigned int tx_bytes; + + /* Heuristics : + * + */ + unsigned int bdg_overflow; + unsigned int pll_empty; + unsigned int rx_intr; + unsigned int rx_poll; + } mmnif_device_stats_t; typedef struct mm_rx_buffer @@ -123,6 +149,7 @@ typedef struct mm_rx_buffer /* memory rx buffer build * - queued : how many packets are in the queue * - pos : which is the next packet to be worked on + * - pending : how many packets are pending * - iv_intr : inform via interrupt or not * - lock: semaphore to lock the local variables to be multi access save * @@ -135,6 +162,7 @@ typedef struct mm_rx_buffer */ uint8_t queued; uint8_t pos; + uint8_t pending; uint8_t iv_intr; @@ -165,6 +193,9 @@ typedef struct mmnif uint8_t tx_queue; uint8_t* tx_buff[MMNIF_TX_QUEUELEN]; mm_rx_buffer_t* rx_buff; + + /* config register banks */ + void* crb[MMNIF_CORES]; /* comunication mailbox */ @@ -243,14 +274,14 @@ __inline uint8_t mmnif_read_rx_pos(uint32_t dest_ip) #endif }; -/* read the pos value from the remote buffer +/* read the inv_intr from the remote buffer * and return it. */ __inline uint8_t mmnif_read_rx_inv_intr(uint32_t dest_ip) { #ifdef WIN32 /* Read the value of the forgein process - * form rx_buff->pos + * form rx_buff->inv_intr */ mm_rx_buffer_t hdr; while(!ReadProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,&hdr,sizeof(hdr),NULL)); @@ -260,6 +291,23 @@ __inline uint8_t mmnif_read_rx_inv_intr(uint32_t dest_ip) #endif }; +/* read the pending value from the remote buffer + * and return it. + */ +__inline uint8_t mmnif_read_rx_pending(uint32_t dest_ip) +{ +#ifdef WIN32 + /* Read the value of the forgein process + * form rx_buff->pending + */ + mm_rx_buffer_t hdr; + while(!ReadProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size,&hdr,sizeof(hdr),NULL)); + return hdr.pending; +#else + return *(uint8_t*)(mpb_start_address + (dest_ip -1 ) * mpb_size +2); +#endif +}; + /* write data to the remote buffer * */ @@ -318,6 +366,26 @@ __inline int mmnif_write_rx_queue(uint32_t dest_ip,uint8_t queue) #endif }; +/* write the new queue value to the remote buffer + * + */ +__inline int mmnif_write_rx_pending(uint32_t dest_ip,uint8_t pending) +{ + /* tell the remote buffer/process + * that there is another packet in the queue + */ +#ifdef WIN32 + uint32_t nr_of_bytes_written = 0; + while(!WriteProcessMemory(hProc,(char*)mpb_start_address + ( dest_ip -1 ) * mpb_size + 2 ,&pending,1,&nr_of_bytes_written)); + return nr_of_bytes_written; +#else + + memcpy((char*)mpb_start_address + ( dest_ip -1 ) * mpb_size ,&queue,1); + + return 1; +#endif +}; + /* trigger an interrupt on the remote processor * */ @@ -329,7 +397,33 @@ __inline int mmnif_trigger_irq(dest_ip) /* NOTE: have to check how the remote interrupt managment works * on the SCC */ - return NULL; + mmnif_t* mmnif = mmnif_dev->state; + int core = (dest_ip - 1) % 2; + int irq_address = mmnif->crb[dest_ip-1]; + unsigned int value; + + if (core == 0) irq_address += RCK_GLCFG0; + else irq_address += RCK_GLCFG1; + + /**/ + value = inportl((void*)irq_address); + + if (!pulse_irq) && (value & RCK_INTR_MASK)) + { + value &= (~(RCK_INTR_MASK|RCK_NMI_MASK)); + outportl((void*)irq_address,value); + } + + value |= RCK_INTR_MASK; + outportl((void*) irq_address,value); + + /**/ + if (pulse_irq) + { + value &= (~(RCK_INTR_MASK|NMI_MASK)); + outportl((void*)irq_address,value); + } + #endif }; @@ -430,17 +524,15 @@ __inline int mmnif_timestamp() } -/* mmnif_get_device_stats(): - * +/* mmnif_get_device_stats(): Returns a copy of the + * current device */ mmnif_device_stats_t mmnif_get_device_stats() { mmnif_device_stats_t stats = {0}; if(!mmnif_dev) - { DEBUGPRINTF("mmnif_get_device_stats(): the device is not initialized yet."); - } else stats = ((mmnif_t*)mmnif_dev->state)->stats; @@ -448,8 +540,8 @@ mmnif_device_stats_t mmnif_get_device_stats() } -/* mmnif_print_stats(): - * +/* mmnif_print_stats(): Print the devices stats of the + * current device */ void mmnif_print_stats() { @@ -465,10 +557,12 @@ void mmnif_print_stats() DEBUGPRINTF("/dev/mmnif - stats: \n"); DEBUGPRINTF("Received: %d packets successfull\n",mmnif->stats.rx); + DEBUGPRINTF("Received: %d bytes",mmnif->stats.rx_bytes); DEBUGPRINTF("interrupts: %d\n",mmnif->stats.rx_intr); DEBUGPRINTF("polling: %d\n",mmnif->stats.rx_poll); DEBUGPRINTF("Received: %d packets containuing errors\n",mmnif->stats.rx_err); DEBUGPRINTF("Transmitted: %d packests successfull",mmnif->stats.tx); + DEBUGPRINTF("Transmitted: %d bytes",mmnif->stats.tx_bytes); DEBUGPRINTF("Transmitted: %d packests were dropped due to errors",mmnif->stats.tx_err); } @@ -530,10 +624,11 @@ err_t mmnif_tx(struct netif* netif, struct pbuf* p) { mmnif_t* mmnif = netif->state; uint8_t slot = mmnif->tx_queue; - uint32_t i; - struct pbuf* q; /* interator */ uint8_t queued; uint8_t pos; + uint8_t pending; + uint32_t i; + struct pbuf* q; /* interator */ uint8_t build_buff = TRUE; uint8_t dest_intr = FALSE; uint32_t dest_ip = mmnif_get_destination(netif,p); @@ -593,26 +688,51 @@ err_t mmnif_tx(struct netif* netif, struct pbuf* p) } /* get the palce the router core is looking for the packet */ + /* lock the dest_ip mm_rx_buffer_hdr */ mmnif_lock_rx_hdr(dest_ip); + /* read and edit needed values */ queued = mmnif_read_rx_queue(dest_ip); pos = mmnif_read_rx_pos(dest_ip); + pending = mmnif_read_rx_pending(dest_ip); + + pending++; + mmnif_write_rx_pending(dest_ip,pending); + + /* and unlock the dest_ip mm_rx_buffer_hdr */ mmnif_unlock_rx_hdr(dest_ip); - pos = (pos + queued) % MMNIF_RX_QUEUELEN; + /* check if there is a space in the queue without overwriting another packet */ + if ((queued + pending) > MMNIF_RX_QUEUELEN) + { + DEBUGPRINTF("mmnif_tx(): too many packet's at once for the remote queue\n"); + goto drop_packet; + } - /* write buffer to buffer & increment the queued packet count */ + pos = (pos + queued + pending -1) % MMNIF_RX_QUEUELEN; + + /* write buffer to buffer & increment the queued packet count + * this can be safely done without locking because this place is + * reserved for us because it has the status "pending" + */ if (build_buff) mmnif_write_rx_buff(dest_ip, pos, mmnif->tx_buff[slot]); else mmnif_write_rx_buffl(dest_ip, pos, p->payload,p->tot_len); - queued++; - + /* like above ensure we are the only ones editing the hdr */ mmnif_lock_rx_hdr(dest_ip); + queued = mmnif_read_rx_queue(dest_ip); + pending = mmnif_read_rx_pending(dest_ip); + queued++; + pending--; + + dest_intr = mmnif_read_rx_inv_intr(dest_ip); + mmnif_write_rx_queue(dest_ip, queued); + mmnif_write_rx_pending(dest_ip, pending); mmnif_unlock_rx_hdr(dest_ip); @@ -622,7 +742,7 @@ err_t mmnif_tx(struct netif* netif, struct pbuf* p) #endif /* if driver is not in polling mode inform core that a message has arrived */ - if (!no_irq) + if (dest_intr) mmnif_trigger_irq(dest_ip); /* free the transmid queue*/ @@ -637,6 +757,7 @@ err_t mmnif_tx(struct netif* netif, struct pbuf* p) LINK_STATS_INC(link.xmit); mmnif->stats.tx++; + mmnif->stats.tx_bytes += p->tot_len; return ERR_OK; @@ -697,8 +818,21 @@ err_t mmnif_init(struct netif* netif) } memset(mmnif->rx_buff, 0, (sizeof(mm_rx_buffer_t) + MMNIF_RX_QUEUELEN* MMNIF_RX_BUFFERLEN)* (MMNIF_CORES-1)); + /* init the lock for the hdr + */ sem_init(&mmnif->rx_buff->lock,1); + /* inform via interrupt should be the dafault + */ + if (!no_irq) + mmnif->rx_buff->iv_intr = TRUE; + + for (i = 0; i < MMNIF_CORES;i+=2) + { + mmnif->crb[i] = crb + RCK_TILE_SIZE*(i/2); + mmnif->crb[i+1] = crb + RCK_TILE_SIZE*(i/2); + } + /* Alloc and clear internal memory for tx_buff */ #ifdef WIN32 @@ -851,6 +985,8 @@ static void mmnif_rx(struct netif* netif) LINK_STATS_INC(link.xmit); mmnif->stats.rx++; + mmnif->stats.rx_bytes += p->tot_len; + if (no_irq) mmnif->stats.rx_poll++; else @@ -877,7 +1013,22 @@ static int mmnif_wait(struct netif* netif, uint32_t poll, int budget) struct pbuf* p = NULL; int err = ERR_OK; unsigned int npackets = 0; - unsigned int quota = budget > mmnif->rx_buff->queued ? mmnif->rx_buff->queued : budget; + unsigned int quota = 0; + + if (budget > mmnif->rx_buff->queued) + { + quota = mmnif->rx_buff->queued; + } + else + { + quota = budget; + mmnif->stats.bdg_overflow++; + /* if (budget overflow too often) + * { + * enable polling and disable interrupts + * } + */ + } /* process up to quota packets from the receive queue */ while (npackets <= quota) @@ -921,7 +1072,7 @@ static int mmnif_wait(struct netif* netif, uint32_t poll, int budget) int mmnif_worker(void* e) { while (active) - mmnif_wait(mmnif_dev,0,5); + mmnif_wait(mmnif_dev,0,MMNIF_WORKER_BUDGET); return NULL; } @@ -946,11 +1097,18 @@ int mmnif_poll(void* e) /*run while driver is up*/ while (active) { - while (mmnif->rx_buff->queued) + while (!mmnif->rx_buff->queued) { tmp32 = mmnif_timestamp(); diff = diff - tmp32 > 0 ? diff - tmp32 : tmp32 - diff; + mmnif->stats.pll_empty++; + /* if (too many emtpy runs) + * { + * enable interrupts and suspend polling + * } + */ } + mmnif->stats.pll_empty--; // Sleep(10); mmnif_rx(mmnif_dev); }