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