static int hvsi_write(struct tty_struct *tty, const unsigned char *buf, int count) { struct hvsi_struct *hp = tty->driver_data; const char *source = buf; unsigned long flags; int total = 0; int origcount = count; spin_lock_irqsave(&hp->lock, flags); pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf); if (!is_open(hp)) { /* we're either closing or not yet open; don't accept data */ pr_debug("%s: not open\n", __FUNCTION__); goto out; } /* * when the hypervisor buffer (16K) fills, data will stay in hp->outbuf * and hvsi_write_worker will be scheduled. subsequent hvsi_write() calls * will see there is no room in outbuf and return. */ while ((count > 0) && (hvsi_write_room(hp->tty) > 0)) { int chunksize = min(count, hvsi_write_room(hp->tty)); BUG_ON(hp->n_outbuf < 0); memcpy(hp->outbuf + hp->n_outbuf, source, chunksize); hp->n_outbuf += chunksize; total += chunksize; source += chunksize; count -= chunksize; hvsi_push(hp); } if (hp->n_outbuf > 0) { /* * we weren't able to write it all to the hypervisor. * schedule another push attempt. */ schedule_delayed_work(&hp->writer, 10); } out: spin_unlock_irqrestore(&hp->lock, flags); if (total != origcount) pr_debug("%s: wanted %i, only wrote %i\n", __FUNCTION__, origcount, total); return total; }
/* hvsi_write_worker will keep rescheduling itself until outbuf is empty */ static void hvsi_write_worker(void *arg) { struct hvsi_struct *hp = (struct hvsi_struct *)arg; unsigned long flags; #ifdef DEBUG static long start_j = 0; if (start_j == 0) start_j = jiffies; #endif /* DEBUG */ spin_lock_irqsave(&hp->lock, flags); pr_debug("%s: %i chars in buffer\n", __FUNCTION__, hp->n_outbuf); if (!is_open(hp)) { /* * We could have a non-open connection if the service processor died * while we were busily scheduling ourselves. In that case, it could * be minutes before the service processor comes back, so only try * again once a second. */ schedule_delayed_work(&hp->writer, HZ); goto out; } hvsi_push(hp); if (hp->n_outbuf > 0) schedule_delayed_work(&hp->writer, 10); else { #ifdef DEBUG pr_debug("%s: outbuf emptied after %li jiffies\n", __FUNCTION__, jiffies - start_j); start_j = 0; #endif /* DEBUG */ wake_up_all(&hp->emptyq); if (test_bit(TTY_DO_WRITE_WAKEUP, &hp->tty->flags) && hp->tty->ldisc.write_wakeup) hp->tty->ldisc.write_wakeup(hp->tty); wake_up_interruptible(&hp->tty->write_wait); } out: spin_unlock_irqrestore(&hp->lock, flags); }
/* hvsi_write_worker will keep rescheduling itself until outbuf is empty */ static void hvsi_write_worker(struct work_struct *work) { struct hvsi_struct *hp = container_of(work, struct hvsi_struct, writer.work); unsigned long flags; #ifdef DEBUG static long start_j = 0; if (start_j == 0) start_j = jiffies; #endif /* DEBUG */ spin_lock_irqsave(&hp->lock, flags); pr_debug("%s: %i chars in buffer\n", __func__, hp->n_outbuf); if (!is_open(hp)) { /* * We could have a non-open connection if the service processor died * while we were busily scheduling ourselves. In that case, it could * be minutes before the service processor comes back, so only try * again once a second. */ schedule_delayed_work(&hp->writer, HZ); goto out; } hvsi_push(hp); if (hp->n_outbuf > 0) schedule_delayed_work(&hp->writer, 10); else { #ifdef DEBUG pr_debug("%s: outbuf emptied after %li jiffies\n", __func__, jiffies - start_j); start_j = 0; #endif /* DEBUG */ wake_up_all(&hp->emptyq); tty_wakeup(hp->tty); } out: spin_unlock_irqrestore(&hp->lock, flags); }