diff options
Diffstat (limited to 'drivers/block/paride/pf.c')
| -rw-r--r-- | drivers/block/paride/pf.c | 144 |
1 files changed, 81 insertions, 63 deletions
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index 5826508f673..9a15fd3c934 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c @@ -118,13 +118,15 @@ #define PF_NAME "pf" #define PF_UNITS 4 +#include <linux/types.h> + /* Here are things one can override from the insmod command. Most are autoprobed by paride unless set here. Verbose is off by default. */ -static int verbose = 0; +static bool verbose = 0; static int major = PF_MAJOR; static char *name = PF_NAME; static int cluster = 64; @@ -152,8 +154,10 @@ enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY}; #include <linux/spinlock.h> #include <linux/blkdev.h> #include <linux/blkpg.h> +#include <linux/mutex.h> #include <asm/uaccess.h> +static DEFINE_MUTEX(pf_mutex); static DEFINE_SPINLOCK(pf_spin_lock); module_param(verbose, bool, 0644); @@ -201,13 +205,13 @@ module_param_array(drive3, int, NULL, 0); #define ATAPI_READ_10 0x28 #define ATAPI_WRITE_10 0x2a -static int pf_open(struct inode *inode, struct file *file); -static void do_pf_request(request_queue_t * q); -static int pf_ioctl(struct inode *inode, struct file *file, +static int pf_open(struct block_device *bdev, fmode_t mode); +static void do_pf_request(struct request_queue * q); +static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo); -static int pf_release(struct inode *inode, struct file *file); +static void pf_release(struct gendisk *disk, fmode_t mode); static int pf_detect(void); static void do_pf_read(void); @@ -241,7 +245,8 @@ static struct pf_unit units[PF_UNITS]; static int pf_identify(struct pf_unit *pf); static void pf_lock(struct pf_unit *pf, int func); static void pf_eject(struct pf_unit *pf); -static int pf_check_media(struct gendisk *disk); +static unsigned int pf_check_events(struct gendisk *disk, + unsigned int clearing); static char pf_scratch[512]; /* scratch block buffer */ @@ -262,13 +267,13 @@ static char *pf_buf; /* buffer for request in progress */ /* kernel glue structures */ -static struct block_device_operations pf_fops = { +static const struct block_device_operations pf_fops = { .owner = THIS_MODULE, .open = pf_open, .release = pf_release, .ioctl = pf_ioctl, .getgeo = pf_getgeo, - .media_changed = pf_check_media, + .check_events = pf_check_events, }; static void __init pf_init_units(void) @@ -296,23 +301,29 @@ static void __init pf_init_units(void) } } -static int pf_open(struct inode *inode, struct file *file) +static int pf_open(struct block_device *bdev, fmode_t mode) { - struct pf_unit *pf = inode->i_bdev->bd_disk->private_data; + struct pf_unit *pf = bdev->bd_disk->private_data; + int ret; + mutex_lock(&pf_mutex); pf_identify(pf); + ret = -ENODEV; if (pf->media_status == PF_NM) - return -ENODEV; + goto out; - if ((pf->media_status == PF_RO) && (file->f_mode & 2)) - return -EROFS; + ret = -EROFS; + if ((pf->media_status == PF_RO) && (mode & FMODE_WRITE)) + goto out; + ret = 0; pf->access++; if (pf->removable) pf_lock(pf, 1); - - return 0; +out: + mutex_unlock(&pf_mutex); + return ret; } static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo) @@ -333,38 +344,44 @@ static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo) return 0; } -static int pf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) { - struct pf_unit *pf = inode->i_bdev->bd_disk->private_data; + struct pf_unit *pf = bdev->bd_disk->private_data; if (cmd != CDROMEJECT) return -EINVAL; if (pf->access != 1) return -EBUSY; + mutex_lock(&pf_mutex); pf_eject(pf); + mutex_unlock(&pf_mutex); + return 0; } -static int pf_release(struct inode *inode, struct file *file) +static void pf_release(struct gendisk *disk, fmode_t mode) { - struct pf_unit *pf = inode->i_bdev->bd_disk->private_data; + struct pf_unit *pf = disk->private_data; - if (pf->access <= 0) - return -EINVAL; + mutex_lock(&pf_mutex); + if (pf->access <= 0) { + mutex_unlock(&pf_mutex); + WARN_ON(1); + return; + } pf->access--; if (!pf->access && pf->removable) pf_lock(pf, 0); - return 0; - + mutex_unlock(&pf_mutex); } -static int pf_check_media(struct gendisk *disk) +static unsigned int pf_check_events(struct gendisk *disk, unsigned int clearing) { - return 1; + return DISK_EVENT_MEDIA_CHANGE; } static inline int status_reg(struct pf_unit *pf) @@ -391,11 +408,11 @@ static int pf_wait(struct pf_unit *pf, int go, int stop, char *fun, char *msg) && (j++ < PF_SPIN)) udelay(PF_SPIN_DEL); - if ((r & (STAT_ERR & stop)) || (j >= PF_SPIN)) { + if ((r & (STAT_ERR & stop)) || (j > PF_SPIN)) { s = read_reg(pf, 7); e = read_reg(pf, 1); p = read_reg(pf, 2); - if (j >= PF_SPIN) + if (j > PF_SPIN) e |= 0x100; if (fun) printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" @@ -488,13 +505,11 @@ static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fu return r; } -#define DBMSG(msg) ((verbose>1)?(msg):NULL) - static void pf_lock(struct pf_unit *pf, int func) { char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 }; - pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "unlock" : "lock"); + pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock"); } static void pf_eject(struct pf_unit *pf) @@ -555,7 +570,7 @@ static void pf_mode_sense(struct pf_unit *pf) { ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 }; char buf[8]; - pf_atapi(pf, ms_cmd, 8, buf, DBMSG("mode sense")); + pf_atapi(pf, ms_cmd, 8, buf, "mode sense"); pf->media_status = PF_RW; if (buf[3] & 0x80) pf->media_status = PF_RO; @@ -591,7 +606,7 @@ static void pf_get_capacity(struct pf_unit *pf) char buf[8]; int bs; - if (pf_atapi(pf, rc_cmd, 8, buf, DBMSG("get capacity"))) { + if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) { pf->media_status = PF_NM; return; } @@ -752,35 +767,35 @@ static int pf_ready(void) static struct request_queue *pf_queue; -static void pf_end_request(int uptodate) +static void pf_end_request(int err) { - if (pf_req) { - end_request(pf_req, uptodate); + if (pf_req && !__blk_end_request_cur(pf_req, err)) pf_req = NULL; - } } -static void do_pf_request(request_queue_t * q) +static void do_pf_request(struct request_queue * q) { if (pf_busy) return; repeat: - pf_req = elv_next_request(q); - if (!pf_req) - return; + if (!pf_req) { + pf_req = blk_fetch_request(q); + if (!pf_req) + return; + } pf_current = pf_req->rq_disk->private_data; - pf_block = pf_req->sector; - pf_run = pf_req->nr_sectors; - pf_count = pf_req->current_nr_sectors; + pf_block = blk_rq_pos(pf_req); + pf_run = blk_rq_sectors(pf_req); + pf_count = blk_rq_cur_sectors(pf_req); if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) { - pf_end_request(0); + pf_end_request(-EIO); goto repeat; } pf_cmd = rq_data_dir(pf_req); - pf_buf = pf_req->buffer; + pf_buf = bio_data(pf_req->bio); pf_retries = 0; pf_busy = 1; @@ -790,7 +805,7 @@ repeat: pi_do_claimed(pf_current->pi, do_pf_write); else { pf_busy = 0; - pf_end_request(0); + pf_end_request(-EIO); goto repeat; } } @@ -804,21 +819,25 @@ static int pf_next_buf(void) pf_buf += 512; pf_block++; if (!pf_run) - return 0; - if (!pf_count) return 1; - spin_lock_irqsave(&pf_spin_lock, saved_flags); - pf_end_request(1); - spin_unlock_irqrestore(&pf_spin_lock, saved_flags); - return 1; + if (!pf_count) { + spin_lock_irqsave(&pf_spin_lock, saved_flags); + pf_end_request(0); + spin_unlock_irqrestore(&pf_spin_lock, saved_flags); + if (!pf_req) + return 1; + pf_count = blk_rq_cur_sectors(pf_req); + pf_buf = bio_data(pf_req->bio); + } + return 0; } -static inline void next_request(int success) +static inline void next_request(int err) { unsigned long saved_flags; spin_lock_irqsave(&pf_spin_lock, saved_flags); - pf_end_request(success); + pf_end_request(err); pf_busy = 0; do_pf_request(pf_queue); spin_unlock_irqrestore(&pf_spin_lock, saved_flags); @@ -841,7 +860,7 @@ static void do_pf_read_start(void) pi_do_claimed(pf_current->pi, do_pf_read_start); return; } - next_request(0); + next_request(-EIO); return; } pf_mask = STAT_DRQ; @@ -860,7 +879,7 @@ static void do_pf_read_drq(void) pi_do_claimed(pf_current->pi, do_pf_read_start); return; } - next_request(0); + next_request(-EIO); return; } pi_read_block(pf_current->pi, pf_buf, 512); @@ -868,7 +887,7 @@ static void do_pf_read_drq(void) break; } pi_disconnect(pf_current->pi); - next_request(1); + next_request(0); } static void do_pf_write(void) @@ -887,7 +906,7 @@ static void do_pf_write_start(void) pi_do_claimed(pf_current->pi, do_pf_write_start); return; } - next_request(0); + next_request(-EIO); return; } @@ -900,7 +919,7 @@ static void do_pf_write_start(void) pi_do_claimed(pf_current->pi, do_pf_write_start); return; } - next_request(0); + next_request(-EIO); return; } pi_write_block(pf_current->pi, pf_buf, 512); @@ -920,11 +939,11 @@ static void do_pf_write_done(void) pi_do_claimed(pf_current->pi, do_pf_write_start); return; } - next_request(0); + next_request(-EIO); return; } pi_disconnect(pf_current->pi); - next_request(1); + next_request(0); } static int __init pf_init(void) @@ -954,8 +973,7 @@ static int __init pf_init(void) return -ENOMEM; } - blk_queue_max_phys_segments(pf_queue, cluster); - blk_queue_max_hw_segments(pf_queue, cluster); + blk_queue_max_segments(pf_queue, cluster); for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) { struct gendisk *disk = pf->disk; |
