diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/aoe/aoe.h | 2 | ||||
-rw-r--r-- | drivers/block/aoe/aoechr.c | 2 | ||||
-rw-r--r-- | drivers/block/aoe/aoecmd.c | 15 | ||||
-rw-r--r-- | drivers/block/as-iosched.c | 1 | ||||
-rw-r--r-- | drivers/block/genhd.c | 25 | ||||
-rw-r--r-- | drivers/block/paride/pg.c | 2 | ||||
-rw-r--r-- | drivers/block/paride/pt.c | 4 | ||||
-rw-r--r-- | drivers/block/sx8.c | 51 | ||||
-rw-r--r-- | drivers/block/ub.c | 4 |
9 files changed, 78 insertions, 28 deletions
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index 0e9e586e9ba3..881c48d941b7 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,5 +1,5 @@ /* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "12" +#define VERSION "14" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c index 45a243096187..41ae0ede619a 100644 --- a/drivers/block/aoe/aoechr.c +++ b/drivers/block/aoe/aoechr.c @@ -224,7 +224,7 @@ aoechr_init(void) return PTR_ERR(aoe_class); } for (i = 0; i < ARRAY_SIZE(chardevs); ++i) - class_device_create(aoe_class, + class_device_create(aoe_class, NULL, MKDEV(AOE_MAJOR, chardevs[i].minor), NULL, chardevs[i].name); diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index b5be4b7d7b5b..5c9c7c1a3d4c 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -8,6 +8,7 @@ #include <linux/blkdev.h> #include <linux/skbuff.h> #include <linux/netdevice.h> +#include <asm/unaligned.h> #include "aoe.h" #define TIMERTICK (HZ / 10) @@ -311,16 +312,16 @@ ataid_complete(struct aoedev *d, unsigned char *id) u16 n; /* word 83: command set supported */ - n = le16_to_cpup((__le16 *) &id[83<<1]); + n = le16_to_cpu(get_unaligned((__le16 *) &id[83<<1])); /* word 86: command set/feature enabled */ - n |= le16_to_cpup((__le16 *) &id[86<<1]); + n |= le16_to_cpu(get_unaligned((__le16 *) &id[86<<1])); if (n & (1<<10)) { /* bit 10: LBA 48 */ d->flags |= DEVFL_EXT; /* word 100: number lba48 sectors */ - ssize = le64_to_cpup((__le64 *) &id[100<<1]); + ssize = le64_to_cpu(get_unaligned((__le64 *) &id[100<<1])); /* set as in ide-disk.c:init_idedisk_capacity */ d->geo.cylinders = ssize; @@ -331,12 +332,12 @@ ataid_complete(struct aoedev *d, unsigned char *id) d->flags &= ~DEVFL_EXT; /* number lba28 sectors */ - ssize = le32_to_cpup((__le32 *) &id[60<<1]); + ssize = le32_to_cpu(get_unaligned((__le32 *) &id[60<<1])); /* NOTE: obsolete in ATA 6 */ - d->geo.cylinders = le16_to_cpup((__le16 *) &id[54<<1]); - d->geo.heads = le16_to_cpup((__le16 *) &id[55<<1]); - d->geo.sectors = le16_to_cpup((__le16 *) &id[56<<1]); + d->geo.cylinders = le16_to_cpu(get_unaligned((__le16 *) &id[54<<1])); + d->geo.heads = le16_to_cpu(get_unaligned((__le16 *) &id[55<<1])); + d->geo.sectors = le16_to_cpu(get_unaligned((__le16 *) &id[56<<1])); } d->ssize = ssize; d->geo.start = 0; diff --git a/drivers/block/as-iosched.c b/drivers/block/as-iosched.c index 4081c36c8c19..564172234819 100644 --- a/drivers/block/as-iosched.c +++ b/drivers/block/as-iosched.c @@ -1344,6 +1344,7 @@ as_add_aliased_request(struct as_data *ad, struct as_rq *arq, struct as_rq *alia * Don't want to have to handle merges. */ as_del_arq_hash(arq); + arq->request->flags |= REQ_NOMERGE; } /* diff --git a/drivers/block/genhd.c b/drivers/block/genhd.c index d42840cc0d1d..486ce1fdeb8c 100644 --- a/drivers/block/genhd.c +++ b/drivers/block/genhd.c @@ -337,10 +337,30 @@ static ssize_t disk_attr_show(struct kobject *kobj, struct attribute *attr, return ret; } +static ssize_t disk_attr_store(struct kobject * kobj, struct attribute * attr, + const char *page, size_t count) +{ + struct gendisk *disk = to_disk(kobj); + struct disk_attribute *disk_attr = + container_of(attr,struct disk_attribute,attr); + ssize_t ret = 0; + + if (disk_attr->store) + ret = disk_attr->store(disk, page, count); + return ret; +} + static struct sysfs_ops disk_sysfs_ops = { .show = &disk_attr_show, + .store = &disk_attr_store, }; +static ssize_t disk_uevent_store(struct gendisk * disk, + const char *buf, size_t count) +{ + kobject_hotplug(&disk->kobj, KOBJ_ADD); + return count; +} static ssize_t disk_dev_read(struct gendisk * disk, char *page) { dev_t base = MKDEV(disk->major, disk->first_minor); @@ -382,6 +402,10 @@ static ssize_t disk_stats_read(struct gendisk * disk, char *page) jiffies_to_msecs(disk_stat_read(disk, io_ticks)), jiffies_to_msecs(disk_stat_read(disk, time_in_queue))); } +static struct disk_attribute disk_attr_uevent = { + .attr = {.name = "uevent", .mode = S_IWUSR }, + .store = disk_uevent_store +}; static struct disk_attribute disk_attr_dev = { .attr = {.name = "dev", .mode = S_IRUGO }, .show = disk_dev_read @@ -404,6 +428,7 @@ static struct disk_attribute disk_attr_stat = { }; static struct attribute * default_attrs[] = { + &disk_attr_uevent.attr, &disk_attr_dev.attr, &disk_attr_range.attr, &disk_attr_removable.attr, diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c index b3982395f22b..82f2d6d2eeef 100644 --- a/drivers/block/paride/pg.c +++ b/drivers/block/paride/pg.c @@ -674,7 +674,7 @@ static int __init pg_init(void) for (unit = 0; unit < PG_UNITS; unit++) { struct pg *dev = &devices[unit]; if (dev->present) { - class_device_create(pg_class, MKDEV(major, unit), + class_device_create(pg_class, NULL, MKDEV(major, unit), NULL, "pg%u", unit); err = devfs_mk_cdev(MKDEV(major, unit), S_IFCHR | S_IRUSR | S_IWUSR, "pg/%u", diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c index d8d35233cf49..686c95573452 100644 --- a/drivers/block/paride/pt.c +++ b/drivers/block/paride/pt.c @@ -971,7 +971,7 @@ static int __init pt_init(void) devfs_mk_dir("pt"); for (unit = 0; unit < PT_UNITS; unit++) if (pt[unit].present) { - class_device_create(pt_class, MKDEV(major, unit), + class_device_create(pt_class, NULL, MKDEV(major, unit), NULL, "pt%d", unit); err = devfs_mk_cdev(MKDEV(major, unit), S_IFCHR | S_IRUSR | S_IWUSR, @@ -980,7 +980,7 @@ static int __init pt_init(void) class_device_destroy(pt_class, MKDEV(major, unit)); goto out_class; } - class_device_create(pt_class, MKDEV(major, unit + 128), + class_device_create(pt_class, NULL, MKDEV(major, unit + 128), NULL, "pt%dn", unit); err = devfs_mk_cdev(MKDEV(major, unit + 128), S_IFCHR | S_IRUSR | S_IWUSR, diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index d57007b92f77..1ded3b433459 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c @@ -1,7 +1,7 @@ /* * sx8.c: Driver for Promise SATA SX8 looks-like-I2O hardware * - * Copyright 2004 Red Hat, Inc. + * Copyright 2004-2005 Red Hat, Inc. * * Author/maintainer: Jeff Garzik <jgarzik@pobox.com> * @@ -31,10 +31,6 @@ #include <asm/semaphore.h> #include <asm/uaccess.h> -MODULE_AUTHOR("Jeff Garzik"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Promise SATA SX8 block driver"); - #if 0 #define CARM_DEBUG #define CARM_VERBOSE_DEBUG @@ -45,9 +41,35 @@ MODULE_DESCRIPTION("Promise SATA SX8 block driver"); #undef CARM_NDEBUG #define DRV_NAME "sx8" -#define DRV_VERSION "0.8" +#define DRV_VERSION "1.0" #define PFX DRV_NAME ": " +MODULE_AUTHOR("Jeff Garzik"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Promise SATA SX8 block driver"); +MODULE_VERSION(DRV_VERSION); + +/* + * SX8 hardware has a single message queue for all ATA ports. + * When this driver was written, the hardware (firmware?) would + * corrupt data eventually, if more than one request was outstanding. + * As one can imagine, having 8 ports bottlenecking on a single + * command hurts performance. + * + * Based on user reports, later versions of the hardware (firmware?) + * seem to be able to survive with more than one command queued. + * + * Therefore, we default to the safe option -- 1 command -- but + * allow the user to increase this. + * + * SX8 should be able to support up to ~60 queued commands (CARM_MAX_REQ), + * but problems seem to occur when you exceed ~30, even on newer hardware. + */ +static int max_queue = 1; +module_param(max_queue, int, 0444); +MODULE_PARM_DESC(max_queue, "Maximum number of queued commands. (min==1, max==30, safe==1)"); + + #define NEXT_RESP(idx) ((idx + 1) % RMSG_Q_LEN) /* 0xf is just arbitrary, non-zero noise; this is sorta like poisoning */ @@ -90,12 +112,10 @@ enum { /* command message queue limits */ CARM_MAX_REQ = 64, /* max command msgs per host */ - CARM_MAX_Q = 1, /* one command at a time */ CARM_MSG_LOW_WATER = (CARM_MAX_REQ / 4), /* refill mark */ /* S/G limits, host-wide and per-request */ CARM_MAX_REQ_SG = 32, /* max s/g entries per request */ - CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */ CARM_MAX_HOST_SG = 600, /* max s/g entries per host */ CARM_SG_LOW_WATER = (CARM_MAX_HOST_SG / 4), /* re-fill mark */ @@ -181,6 +201,10 @@ enum { FL_DYN_MAJOR = (1 << 17), }; +enum { + CARM_SG_BOUNDARY = 0xffffUL, /* s/g segment boundary */ +}; + enum scatter_gather_types { SGT_32BIT = 0, SGT_64BIT = 1, @@ -218,7 +242,6 @@ static const char *state_name[] = { struct carm_port { unsigned int port_no; - unsigned int n_queued; struct gendisk *disk; struct carm_host *host; @@ -448,7 +471,7 @@ static inline int carm_lookup_bucket(u32 msg_size) for (i = 0; i < ARRAY_SIZE(msg_sizes); i++) if (msg_size <= msg_sizes[i]) return i; - + return -ENOENT; } @@ -509,7 +532,7 @@ static struct carm_request *carm_get_request(struct carm_host *host) if (host->hw_sg_used >= (CARM_MAX_HOST_SG - CARM_MAX_REQ_SG)) return NULL; - for (i = 0; i < CARM_MAX_Q; i++) + for (i = 0; i < max_queue; i++) if ((host->msg_alloc & (1ULL << i)) == 0) { struct carm_request *crq = &host->req[i]; crq->port = NULL; @@ -521,14 +544,14 @@ static struct carm_request *carm_get_request(struct carm_host *host) assert(host->n_msgs <= CARM_MAX_REQ); return crq; } - + DPRINTK("no request available, returning NULL\n"); return NULL; } static int carm_put_request(struct carm_host *host, struct carm_request *crq) { - assert(crq->tag < CARM_MAX_Q); + assert(crq->tag < max_queue); if (unlikely((host->msg_alloc & (1ULL << crq->tag)) == 0)) return -EINVAL; /* tried to clear a tag that was not active */ @@ -791,7 +814,7 @@ static inline void carm_end_rq(struct carm_host *host, struct carm_request *crq, int is_ok) { carm_end_request_queued(host, crq, is_ok); - if (CARM_MAX_Q == 1) + if (max_queue == 1) carm_round_robin(host); else if ((host->n_msgs <= CARM_MSG_LOW_WATER) && (host->hw_sg_used <= CARM_SG_LOW_WATER)) { diff --git a/drivers/block/ub.c b/drivers/block/ub.c index ed4d5006fe62..bfb23d543ff7 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -1512,7 +1512,7 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) scmd->nsg = 1; sg = &scmd->sgv[0]; sg->page = virt_to_page(sc->top_sense); - sg->offset = (unsigned int)sc->top_sense & (PAGE_SIZE-1); + sg->offset = (unsigned long)sc->top_sense & (PAGE_SIZE-1); sg->length = UB_SENSE_SIZE; scmd->len = UB_SENSE_SIZE; scmd->lun = cmd->lun; @@ -1891,7 +1891,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, cmd->nsg = 1; sg = &cmd->sgv[0]; sg->page = virt_to_page(p); - sg->offset = (unsigned int)p & (PAGE_SIZE-1); + sg->offset = (unsigned long)p & (PAGE_SIZE-1); sg->length = 8; cmd->len = 8; cmd->lun = lun; |