aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/pktcdvd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/pktcdvd.c')
-rw-r--r--drivers/block/pktcdvd.c53
1 files changed, 28 insertions, 25 deletions
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index cd16813effc5..4e7dbcc425ff 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -129,7 +129,7 @@ static struct bio *pkt_bio_alloc(int nr_iovecs)
129/* 129/*
130 * Allocate a packet_data struct 130 * Allocate a packet_data struct
131 */ 131 */
132static struct packet_data *pkt_alloc_packet_data(void) 132static struct packet_data *pkt_alloc_packet_data(int frames)
133{ 133{
134 int i; 134 int i;
135 struct packet_data *pkt; 135 struct packet_data *pkt;
@@ -138,11 +138,12 @@ static struct packet_data *pkt_alloc_packet_data(void)
138 if (!pkt) 138 if (!pkt)
139 goto no_pkt; 139 goto no_pkt;
140 140
141 pkt->w_bio = pkt_bio_alloc(PACKET_MAX_SIZE); 141 pkt->frames = frames;
142 pkt->w_bio = pkt_bio_alloc(frames);
142 if (!pkt->w_bio) 143 if (!pkt->w_bio)
143 goto no_bio; 144 goto no_bio;
144 145
145 for (i = 0; i < PAGES_PER_PACKET; i++) { 146 for (i = 0; i < frames / FRAMES_PER_PAGE; i++) {
146 pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO); 147 pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO);
147 if (!pkt->pages[i]) 148 if (!pkt->pages[i])
148 goto no_page; 149 goto no_page;
@@ -150,7 +151,7 @@ static struct packet_data *pkt_alloc_packet_data(void)
150 151
151 spin_lock_init(&pkt->lock); 152 spin_lock_init(&pkt->lock);
152 153
153 for (i = 0; i < PACKET_MAX_SIZE; i++) { 154 for (i = 0; i < frames; i++) {
154 struct bio *bio = pkt_bio_alloc(1); 155 struct bio *bio = pkt_bio_alloc(1);
155 if (!bio) 156 if (!bio)
156 goto no_rd_bio; 157 goto no_rd_bio;
@@ -160,14 +161,14 @@ static struct packet_data *pkt_alloc_packet_data(void)
160 return pkt; 161 return pkt;
161 162
162no_rd_bio: 163no_rd_bio:
163 for (i = 0; i < PACKET_MAX_SIZE; i++) { 164 for (i = 0; i < frames; i++) {
164 struct bio *bio = pkt->r_bios[i]; 165 struct bio *bio = pkt->r_bios[i];
165 if (bio) 166 if (bio)
166 bio_put(bio); 167 bio_put(bio);
167 } 168 }
168 169
169no_page: 170no_page:
170 for (i = 0; i < PAGES_PER_PACKET; i++) 171 for (i = 0; i < frames / FRAMES_PER_PAGE; i++)
171 if (pkt->pages[i]) 172 if (pkt->pages[i])
172 __free_page(pkt->pages[i]); 173 __free_page(pkt->pages[i]);
173 bio_put(pkt->w_bio); 174 bio_put(pkt->w_bio);
@@ -184,12 +185,12 @@ static void pkt_free_packet_data(struct packet_data *pkt)
184{ 185{
185 int i; 186 int i;
186 187
187 for (i = 0; i < PACKET_MAX_SIZE; i++) { 188 for (i = 0; i < pkt->frames; i++) {
188 struct bio *bio = pkt->r_bios[i]; 189 struct bio *bio = pkt->r_bios[i];
189 if (bio) 190 if (bio)
190 bio_put(bio); 191 bio_put(bio);
191 } 192 }
192 for (i = 0; i < PAGES_PER_PACKET; i++) 193 for (i = 0; i < pkt->frames / FRAMES_PER_PAGE; i++)
193 __free_page(pkt->pages[i]); 194 __free_page(pkt->pages[i]);
194 bio_put(pkt->w_bio); 195 bio_put(pkt->w_bio);
195 kfree(pkt); 196 kfree(pkt);
@@ -204,17 +205,17 @@ static void pkt_shrink_pktlist(struct pktcdvd_device *pd)
204 list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) { 205 list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) {
205 pkt_free_packet_data(pkt); 206 pkt_free_packet_data(pkt);
206 } 207 }
208 INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
207} 209}
208 210
209static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets) 211static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
210{ 212{
211 struct packet_data *pkt; 213 struct packet_data *pkt;
212 214
213 INIT_LIST_HEAD(&pd->cdrw.pkt_free_list); 215 BUG_ON(!list_empty(&pd->cdrw.pkt_free_list));
214 INIT_LIST_HEAD(&pd->cdrw.pkt_active_list); 216
215 spin_lock_init(&pd->cdrw.active_list_lock);
216 while (nr_packets > 0) { 217 while (nr_packets > 0) {
217 pkt = pkt_alloc_packet_data(); 218 pkt = pkt_alloc_packet_data(pd->settings.size >> 2);
218 if (!pkt) { 219 if (!pkt) {
219 pkt_shrink_pktlist(pd); 220 pkt_shrink_pktlist(pd);
220 return 0; 221 return 0;
@@ -949,7 +950,7 @@ try_next_bio:
949 950
950 pd->current_sector = zone + pd->settings.size; 951 pd->current_sector = zone + pd->settings.size;
951 pkt->sector = zone; 952 pkt->sector = zone;
952 pkt->frames = pd->settings.size >> 2; 953 BUG_ON(pkt->frames != pd->settings.size >> 2);
953 pkt->write_size = 0; 954 pkt->write_size = 0;
954 955
955 /* 956 /*
@@ -1985,8 +1986,14 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
1985 if ((ret = pkt_set_segment_merging(pd, q))) 1986 if ((ret = pkt_set_segment_merging(pd, q)))
1986 goto out_unclaim; 1987 goto out_unclaim;
1987 1988
1988 if (write) 1989 if (write) {
1990 if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
1991 printk("pktcdvd: not enough memory for buffers\n");
1992 ret = -ENOMEM;
1993 goto out_unclaim;
1994 }
1989 printk("pktcdvd: %lukB available on disc\n", lba << 1); 1995 printk("pktcdvd: %lukB available on disc\n", lba << 1);
1996 }
1990 1997
1991 return 0; 1998 return 0;
1992 1999
@@ -2012,6 +2019,8 @@ static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
2012 pkt_set_speed(pd, MAX_SPEED, MAX_SPEED); 2019 pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
2013 bd_release(pd->bdev); 2020 bd_release(pd->bdev);
2014 blkdev_put(pd->bdev); 2021 blkdev_put(pd->bdev);
2022
2023 pkt_shrink_pktlist(pd);
2015} 2024}
2016 2025
2017static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor) 2026static struct pktcdvd_device *pkt_find_dev_from_minor(int dev_minor)
@@ -2377,12 +2386,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
2377 /* This is safe, since we have a reference from open(). */ 2386 /* This is safe, since we have a reference from open(). */
2378 __module_get(THIS_MODULE); 2387 __module_get(THIS_MODULE);
2379 2388
2380 if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
2381 printk("pktcdvd: not enough memory for buffers\n");
2382 ret = -ENOMEM;
2383 goto out_mem;
2384 }
2385
2386 pd->bdev = bdev; 2389 pd->bdev = bdev;
2387 set_blocksize(bdev, CD_FRAMESIZE); 2390 set_blocksize(bdev, CD_FRAMESIZE);
2388 2391
@@ -2393,7 +2396,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
2393 if (IS_ERR(pd->cdrw.thread)) { 2396 if (IS_ERR(pd->cdrw.thread)) {
2394 printk("pktcdvd: can't start kernel thread\n"); 2397 printk("pktcdvd: can't start kernel thread\n");
2395 ret = -ENOMEM; 2398 ret = -ENOMEM;
2396 goto out_thread; 2399 goto out_mem;
2397 } 2400 }
2398 2401
2399 proc = create_proc_entry(pd->name, 0, pkt_proc); 2402 proc = create_proc_entry(pd->name, 0, pkt_proc);
@@ -2404,8 +2407,6 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
2404 DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b)); 2407 DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
2405 return 0; 2408 return 0;
2406 2409
2407out_thread:
2408 pkt_shrink_pktlist(pd);
2409out_mem: 2410out_mem:
2410 blkdev_put(bdev); 2411 blkdev_put(bdev);
2411 /* This is safe: open() is still holding a reference. */ 2412 /* This is safe: open() is still holding a reference. */
@@ -2501,6 +2502,10 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
2501 goto out_mem; 2502 goto out_mem;
2502 pd->disk = disk; 2503 pd->disk = disk;
2503 2504
2505 INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
2506 INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
2507 spin_lock_init(&pd->cdrw.active_list_lock);
2508
2504 spin_lock_init(&pd->lock); 2509 spin_lock_init(&pd->lock);
2505 spin_lock_init(&pd->iosched.lock); 2510 spin_lock_init(&pd->iosched.lock);
2506 sprintf(pd->name, "pktcdvd%d", idx); 2511 sprintf(pd->name, "pktcdvd%d", idx);
@@ -2565,8 +2570,6 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
2565 2570
2566 blkdev_put(pd->bdev); 2571 blkdev_put(pd->bdev);
2567 2572
2568 pkt_shrink_pktlist(pd);
2569
2570 remove_proc_entry(pd->name, pkt_proc); 2573 remove_proc_entry(pd->name, pkt_proc);
2571 DPRINTK("pktcdvd: writer %s unmapped\n", pd->name); 2574 DPRINTK("pktcdvd: writer %s unmapped\n", pd->name);
2572 2575