static inline int tx_link_write_error(txdrv_t *tx, const char *func) { struct attr *attr = tx->opaque; if (is_temporary_error(errno) || ENOBUFS == errno) return 0; switch (errno) { /* * The following are probably due to bugs in the libc, but this is in * the same vein as write() failing with -1 whereas errno == 0! Be more * robust against bugs in the components we rely on. --RAM, 09/10/2003 */ case EINPROGRESS: /* Weird, but seen it -- RAM, 07/10/2003 */ g_warning("%s(fd=%d) failed with weird errno = %d: %m -- " "assuming EAGAIN", func, attr->wio->fd(attr->wio), errno); return 0; case EPIPE: case ECONNRESET: case ECONNABORTED: tx_error(tx); attr->cb->eof_remove(tx->owner, _("Write failed: %s"), g_strerror(errno)); return -1; default: { wrap_io_t *wio = ((struct attr *) tx->opaque)->wio; int fd = wio->fd(wio); g_warning("%s: write failed on fd #%d with unexpected error: %m", func, fd); } /* FALL THROUGH */ case ENOSPC: #ifdef EDQUOT case EDQUOT: #endif /* EDQUOT */ #ifdef ESHUTDOWN case ESHUTDOWN: #endif /* ESHUTDOWN */ case EACCES: case EFBIG: case EHOSTDOWN: case EHOSTUNREACH: case EIO: case ENETDOWN: case ENETUNREACH: case ETIMEDOUT: tx_error(tx); attr->cb->eof_shutdown(tx->owner, _("Write failed: %s"), g_strerror(errno)); return -1; } return 0; /* Just in case */ }
static irqreturn_t rio_interrupt (int irq, void *dev_instance) { struct net_device *dev = dev_instance; struct netdev_private *np; unsigned int_status; long ioaddr; int cnt = max_intrloop; int handled = 0; ioaddr = dev->base_addr; np = netdev_priv(dev); while (1) { int_status = readw (ioaddr + IntStatus); writew (int_status, ioaddr + IntStatus); int_status &= DEFAULT_INTR; if (int_status == 0 || --cnt < 0) break; handled = 1; /* Processing received packets */ if (int_status & RxDMAComplete) receive_packet (dev); /* TxDMAComplete interrupt */ if ((int_status & (TxDMAComplete|IntRequested))) { int tx_status; tx_status = readl (ioaddr + TxStatus); if (tx_status & 0x01) tx_error (dev, tx_status); /* Free used tx skbuffs */ rio_free_tx (dev, 1); } /* Handle uncommon events */ if (int_status & (HostError | LinkEvent | UpdateStats)) rio_error (dev, int_status); } if (np->cur_tx != np->old_tx) writel (100, ioaddr + CountDown); return IRQ_RETVAL(handled); }
/** * Invoked when the output file descriptor can accept more data. */ static void is_writable(void *data, int unused_source, inputevt_cond_t cond) { txdrv_t *tx = data; struct attr *attr = tx->opaque; (void) unused_source; g_assert(tx->flags & TX_SERVICE); /* Servicing enabled */ if (cond & INPUT_EVENT_EXCEPTION) { tx_error(tx); attr->cb->eof_remove(tx->owner, _("Write failed (Input Exception)")); return; } /* * We can write again on the node's socket. Service the queue. */ g_assert(tx->srv_routine); tx->srv_routine(tx->srv_arg); }
/** * Flush compression within filling buffer. * * @return success status, failure meaning we shutdown. */ static bool deflate_flush(txdrv_t *tx) { struct attr *attr = tx->opaque; z_streamp outz = attr->outz; struct buffer *b; int ret; int old_avail; retry: b = &attr->buf[attr->fill_idx]; /* Buffer we fill */ if (tx_deflate_debugging(9)) { g_debug("TX %s: (%s) flushing %zu bytes " "(buffer #%d, flushed %zu, unflushed %zu) [%c%c]", G_STRFUNC, gnet_host_to_string(&tx->host), b->wptr - b->rptr, attr->fill_idx, attr->flushed, attr->unflushed, (attr->flags & DF_FLOWC) ? 'C' : '-', (attr->flags & DF_FLUSH) ? 'f' : '-'); } /* * Prepare call to deflate(). * * We force avail_in to 0, and don't touch next_in: no input should * be consumed. */ outz->next_out = cast_to_pointer(b->wptr); outz->avail_out = old_avail = b->end - b->wptr; outz->avail_in = 0; g_assert(outz->avail_out > 0); ret = deflate(outz, (tx->flags & TX_CLOSING) ? Z_FINISH : Z_SYNC_FLUSH); switch (ret) { case Z_BUF_ERROR: /* Nothing to flush */ goto done; case Z_OK: case Z_STREAM_END: break; default: attr->flags |= DF_SHUTDOWN; tx_error(tx); /* XXX: The callback must not destroy the tx! */ (*attr->cb->shutdown)(tx->owner, "Compression flush failed: %s", zlib_strerror(ret)); return FALSE; } { size_t written; written = old_avail - outz->avail_out; b->wptr += written; attr->flushed += written; if (NULL != attr->cb->add_tx_deflated) attr->cb->add_tx_deflated(tx->owner, written); } /* * Check whether avail_out is 0. * * If it is, then we lacked room to complete the flush. Try to send the * buffer and continue. */ if (0 == outz->avail_out) { if (attr->send_idx >= 0) { /* Send buffer not sent yet */ attr->flags |= DF_FLUSH; /* In flush mode */ deflate_set_flowc(tx, TRUE); /* Starting flow-control */ return TRUE; } deflate_rotate_and_send(tx); /* Can set TX_ERROR */ if (tx->flags & TX_ERROR) return FALSE; goto retry; } done: deflate_flushed(tx); return TRUE; /* Fully flushed */ }
/** * Write ready-to-be-sent buffer to the lower layer. */ static void deflate_send(txdrv_t *tx) { struct attr *attr = tx->opaque; struct buffer *b; size_t len; /**< Amount of bytes to send */ ssize_t r; g_assert(attr->send_idx >= 0); /* We have something to send */ g_assert(attr->send_idx < BUFFER_COUNT); /* * Compute data to be sent. */ b = &attr->buf[attr->send_idx]; /* Buffer to send */ len = b->wptr - b->rptr; g_assert(len > 0 && len <= INT_MAX); /* * Write as much as possible. */ r = tx_write(tx->lower, b->rptr, len); if (tx_deflate_debugging(9)) { g_debug("TX %s: (%s) wrote %zu/%zu bytes (buffer #%d) [%c%c]", G_STRFUNC, gnet_host_to_string(&tx->host), r, len, attr->send_idx, (attr->flags & DF_FLOWC) ? 'C' : '-', (attr->flags & DF_FLUSH) ? 'f' : '-'); } if ((ssize_t) -1 == r) { tx_error(tx); return; } /* * If we wrote everything, we're done. */ if ((size_t) r == len) { if (tx_deflate_debugging(9)) { g_debug("TX %s: (%s) buffer #%d is empty", G_STRFUNC, gnet_host_to_string(&tx->host), attr->send_idx); } attr->send_idx = -1; /* Signals: is now free */ b->wptr = b->rptr = b->arena; /* Buffer is now empty */ return; } /* * We were unable to send the whole buffer. Enable servicing when * the lower layer will be ready for more input. */ b->rptr += r; g_assert(b->rptr < b->wptr); /* We haven't written everything */ tx_srv_enable(tx->lower); }