1e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat/* 2e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * blktrace output analysis: generate a timeline & gather statistics 3e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 4e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Copyright (C) 2006 Alan D. Brunelle <Alan.Brunelle@hp.com> 5e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 6e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * This program is free software; you can redistribute it and/or modify 7e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * it under the terms of the GNU General Public License as published by 8e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * the Free Software Foundation; either version 2 of the License, or 9e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * (at your option) any later version. 10e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 11e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * This program is distributed in the hope that it will be useful, 12e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * but WITHOUT ANY WARRANTY; without even the implied warranty of 13e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * GNU General Public License for more details. 15e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 16e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * You should have received a copy of the GNU General Public License 17e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * along with this program; if not, write to the Free Software 18e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat * 20e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat */ 21e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include <stdio.h> 22e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#include "globals.h" 23e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 24e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define N_DEV_HASH 128 25e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat#define DEV_HASH(dev) ((MAJOR(dev) ^ MINOR(dev)) & (N_DEV_HASH - 1)) 26e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct list_head dev_heads[N_DEV_HASH]; 27e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 28e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void *dip_rb_mkhds(void) 29e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 30e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat size_t len = N_IOP_TYPES * sizeof(struct rb_root); 31e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return memset(malloc(len), 0, len); 32e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 33e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 34e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void __destroy(struct rb_node *n) 35e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 36e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (n) { 37e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io *iop = rb_entry(n, struct io, rb_node); 38e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 39e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __destroy(n->rb_left); 40e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __destroy(n->rb_right); 41e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat io_release(iop); 42e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 43e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 44e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 45e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic void __destroy_heads(struct rb_root *roots) 46e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 47e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int i; 48e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 49e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat for (i = 0; i < N_IOP_TYPES; i++) 50e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __destroy(roots[i].rb_node); 51e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 52e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(roots); 53e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 54e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 55e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid init_dev_heads(void) 56e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 57e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int i; 58e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat for (i = 0; i < N_DEV_HASH; i++) 59e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat INIT_LIST_HEAD(&dev_heads[i]); 60e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 61e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 62e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct d_info *__dip_find(__u32 device) 63e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 64e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct d_info *dip; 65e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head *p; 66e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 67e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __list_for_each(p, &dev_heads[DEV_HASH(device)]) { 68e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip = list_entry(p, struct d_info, hash_head); 69e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (device == dip->device) 70e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return dip; 71e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 72e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 73e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return NULL; 74e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 75e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 76e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid __dip_exit(struct d_info *dip) 77e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 78e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_del(&dip->all_head); 79e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __destroy_heads(dip->heads); 80e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat region_exit(&dip->regions); 81e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat seeki_free(dip->seek_handle); 82e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat seeki_free(dip->q2q_handle); 83e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat aqd_free(dip->aqd_handle); 84e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat plat_free(dip->q2d_plat_handle); 85e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat plat_free(dip->q2c_plat_handle); 86e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat plat_free(dip->d2c_plat_handle); 87e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat bno_dump_free(dip->bno_dump_handle); 88e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat unplug_hist_free(dip->up_hist_handle); 89e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (output_all_data) 90e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat q2d_free(dip->q2d_priv); 91e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dip->pit_fp) 92e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat fclose(dip->pit_fp); 93e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat free(dip); 94e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 95e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 96e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid dip_exit(void) 97e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 98e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head *p, *q; 99e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 100e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_for_each_safe(p, q, &all_devs) { 101e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct d_info *dip = list_entry(p, struct d_info, all_head); 102e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __dip_exit(dip); 103e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 104e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 105e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 106e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline char *mkhandle(char *str, __u32 device, char *post) 107e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 108e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int mjr = device >> MINORBITS; 109e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int mnr = device & ((1 << MINORBITS) - 1); 110e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 111e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat sprintf(str, "%03d,%03d%s", mjr, mnr, post); 112e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return str; 113e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 114e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 115e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline FILE *open_pit(char *str) 116e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 117e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat FILE *fp = my_fopen(str, "w"); 118e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 119e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (fp == NULL) 120e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat perror(str); 121e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 122e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return fp; 123e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 124e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 125e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct d_info *dip_alloc(__u32 device, struct io *iop) 126e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 127e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct d_info *dip = __dip_find(device); 128e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 129e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dip == NULL) { 130e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char str[256]; 131e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 132e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip = malloc(sizeof(struct d_info)); 133e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat memset(dip, 0, sizeof(*dip)); 134e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->heads = dip_rb_mkhds(); 135e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat region_init(&dip->regions); 136e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->device = device; 137e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->last_q = (__u64)-1; 138e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->devmap = dev_map_find(device); 139e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->bno_dump_handle = bno_dump_alloc(device); 140e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->up_hist_handle = unplug_hist_alloc(device); 141e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->seek_handle = seeki_alloc(mkhandle(str, device, "_d2d")); 142e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->q2q_handle = seeki_alloc(mkhandle(str, device, "_q2q")); 143e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->aqd_handle = aqd_alloc(mkhandle(str, device, "_aqd")); 144e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->q2d_plat_handle = 145e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat plat_alloc(mkhandle(str, device, "_q2d_plat")); 146e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->q2c_plat_handle = 147e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat plat_alloc(mkhandle(str, device, "_q2c_plat")); 148e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->d2c_plat_handle = 149e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat plat_alloc(mkhandle(str, device, "_d2c_plat")); 150e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat latency_alloc(dip); 151e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_add_tail(&dip->hash_head, &dev_heads[DEV_HASH(device)]); 152e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_add_tail(&dip->all_head, &all_devs); 153e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->start_time = BIT_TIME(iop->t.time); 154e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->pre_culling = 1; 155e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (output_all_data) 156e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->q2d_priv = q2d_alloc(); 157e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat n_devs++; 158e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (per_io_trees) 159e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->pit_fp = open_pit(mkhandle(per_io_trees, 160e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat device, "_pit.dat")); 161e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 162e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 163e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dip->pre_culling) { 164e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (iop->type == IOP_Q || iop->type == IOP_A) 165e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->pre_culling = 0; 166e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat else 167e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return NULL; 168e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 169e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 170e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iop->linked = dip_rb_ins(dip, iop); 171e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->end_time = BIT_TIME(iop->t.time); 172e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 173e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return dip; 174e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 175e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 176e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid iop_rem_dip(struct io *iop) 177e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 178e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (iop->linked) { 179e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip_rb_rem(iop); 180e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat iop->linked = 0; 181e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 182e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 183e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 184e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid dip_foreach(struct io *iop, enum iop_type type, 185e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat void (*fnc)(struct io *iop, struct io *this), int rm_after) 186e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 187e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (rm_after) { 188e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat LIST_HEAD(head); 189e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct io *this; 190e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head *p, *q; 191e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 192e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip_rb_fe(iop->dip, type, iop, fnc, &head); 193e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_for_each_safe(p, q, &head) { 194e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat this = list_entry(p, struct io, f_head); 195e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_del(&this->f_head); 196e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat io_release(this); 197e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 198e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } else 199e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip_rb_fe(iop->dip, type, iop, fnc, NULL); 200e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 201e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 202e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid dip_foreach_list(struct io *iop, enum iop_type type, struct list_head *hd) 203e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 204e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip_rb_fe(iop->dip, type, iop, NULL, hd); 205e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 206e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 207e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstruct io *dip_find_sec(struct d_info *dip, enum iop_type type, __u64 sec) 208e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 209e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat return dip_rb_find_sec(dip, type, sec); 210e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 211e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 212e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid dip_foreach_out(void (*func)(struct d_info *, void *), void *arg) 213e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 214e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (devices == NULL) { 215e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head *p; 216e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __list_for_each(p, &all_devs) 217e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat func(list_entry(p, struct d_info, all_head), arg); 218e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } else { 219e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat int i; 220e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct d_info *dip; 221e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat unsigned int mjr, mnr; 222e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat char *p = devices; 223e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 224e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat while (p && ((i = sscanf(p, "%u,%u", &mjr, &mnr)) == 2)) { 225e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip = __dip_find((__u32)((mjr << MINORBITS) | mnr)); 226e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat func(dip, arg); 227e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat p = strchr(p, ';'); 228e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (p) p++; 229e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 230e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 231e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 232e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 233e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid dip_plug(__u32 dev, double cur_time) 234e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 235e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct d_info *dip = __dip_find(dev); 236e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 237e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dip && !dip->is_plugged) { 238e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->is_plugged = 1; 239e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->last_plug = cur_time; 240e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 241e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 242e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 243e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatstatic inline void unplug(struct d_info *dip, double cur_time) 244e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 245e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->is_plugged = 0; 246e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->plugged_time += (cur_time - dip->last_plug); 247e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 248e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 249e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid dip_unplug(__u32 dev, double cur_time, __u64 nios_up) 250e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 251e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct d_info *dip = __dip_find(dev); 252e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 253e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dip && dip->is_plugged) { 254e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->nplugs++; 255e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->nios_up += nios_up; 256e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat unplug(dip, cur_time); 257e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 258e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 259e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 260e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid dip_unplug_tm(__u32 dev, double cur_time, __u64 nios_up) 261e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 262e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct d_info *dip = __dip_find(dev); 263e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 264e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dip && dip->is_plugged) { 265e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->nios_upt += nios_up; 266e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat dip->nplugs_t++; 267e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat unplug(dip, cur_time); 268e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 269e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 270e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 271e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehatvoid dip_cleanup(void) 272e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat{ 273e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct list_head *p, *q; 274e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 275e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat list_for_each_safe(p, q, &all_devs) { 276e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat struct d_info *dip = list_entry(p, struct d_info, all_head); 277e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat 278e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat if (dip->n_qs == 0 && dip->n_ds == 0) 279e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat __dip_exit(dip); 280e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat } 281e20e1347b9914aa05e30548c15d7cd5e412cc0e2San Mehat} 282