i2o_block.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 1,421 行 · 第 1/3 页
C
1,421 行
q = dev->gd->queue; if (unlikely(!dev->i2o_dev)) { /* * This is HACK, but Intel Integrated RAID allows user * to delete a volume that is claimed, locked, and in use * by the OS. We have to check for a reply from a * non-existent device and flag it as an error or the system * goes kaput... */ req->errors++; printk(KERN_WARNING "I2O Block: Data transfer to deleted device!\n"); spin_lock_irqsave(q->queue_lock, flags); while (end_that_request_chunk (req, !req->errors, readl(&msg->body[1]))) ; end_that_request_last(req); dev->open_queue_depth--; list_del(&ireq->queue); blk_start_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); return -1; } /* * Lets see what is cooking. We stuffed the * request in the context. */ st = readl(&msg->body[0]) >> 24; if (st != 0) { int err; char *bsa_errors[] = { "Success", "Media Error", "Failure communicating to device", "Device Failure", "Device is not ready", "Media not present", "Media is locked by another user", "Media has failed", "Failure communicating to device", "Device bus failure", "Device is locked by another user", "Device is write protected", "Device has reset", "Volume has changed, waiting for acknowledgement" }; err = readl(&msg->body[0]) & 0xffff; /* * Device not ready means two things. One is that the * the thing went offline (but not a removal media) * * The second is that you have a SuperTrak 100 and the * firmware got constipated. Unlike standard i2o card * setups the supertrak returns an error rather than * blocking for the timeout in these cases. * * Don't stick a supertrak100 into cache aggressive modes */ printk(KERN_ERR "\n/dev/%s error: %s", dev->gd->disk_name, bsa_errors[readl(&msg->body[0]) & 0xffff]); if (readl(&msg->body[0]) & 0x00ff0000) printk(" - DDM attempted %d retries", (readl(&msg->body[0]) >> 16) & 0x00ff); printk(".\n"); req->errors++; } else req->errors = 0; if (!end_that_request_chunk(req, !req->errors, readl(&msg->body[1]))) { add_disk_randomness(req->rq_disk); spin_lock_irqsave(q->queue_lock, flags); end_that_request_last(req); dev->open_queue_depth--; list_del(&ireq->queue); blk_start_queue(q); spin_unlock_irqrestore(q->queue_lock, flags); i2o_block_sglist_free(ireq); i2o_block_request_free(ireq); } else printk(KERN_ERR "still remaining chunks\n"); return 1;};static void i2o_block_event(struct i2o_event *evt){ printk(KERN_INFO "block-osm: event received\n");};#if 0static int i2o_block_event(void *dummy){ unsigned int evt; unsigned long flags; struct i2o_block_device *dev; int unit; //The only event that has data is the SCSI_SMART event. struct i2o_reply { u32 header[4]; u32 evt_indicator; u8 ASC; u8 ASCQ; u16 pad; u8 data[16]; } *evt_local; daemonize("i2oblock"); allow_signal(SIGKILL); evt_running = 1; while (1) { if (down_interruptible(&i2ob_evt_sem)) { evt_running = 0; printk("exiting..."); break; } /* * Keep another CPU/interrupt from overwriting the * message while we're reading it * * We stuffed the unit in the TxContext and grab the event mask * None of the BSA we care about events have EventData */ spin_lock_irqsave(&i2ob_evt_lock, flags); evt_local = (struct i2o_reply *)evt_msg; spin_unlock_irqrestore(&i2ob_evt_lock, flags); unit = le32_to_cpu(evt_local->header[3]); evt = le32_to_cpu(evt_local->evt_indicator); dev = &i2o_blk_dev[unit]; switch (evt) { /* * New volume loaded on same TID, so we just re-install. * The TID/controller don't change as it is the same * I2O device. It's just new media that we have to * rescan. */ case I2O_EVT_IND_BSA_VOLUME_LOAD: { i2ob_install_device(dev->i2o_device->iop, dev->i2o_device, unit); add_disk(dev->gendisk); break; } /* * No media, so set all parameters to 0 and set the media * change flag. The I2O device is still valid, just doesn't * have media, so we don't want to clear the controller or * device pointer. */ case I2O_EVT_IND_BSA_VOLUME_UNLOAD: { struct gendisk *p = dev->gendisk; blk_queue_max_sectors(dev->gendisk->queue, 0); del_gendisk(p); put_disk(p); dev->gendisk = NULL; dev->media_change_flag = 1; break; } case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ: printk(KERN_WARNING "%s: Attempt to eject locked media\n", dev->i2o_device->dev_name); break; /* * The capacity has changed and we are going to be * updating the max_sectors and other information * about this disk. We try a revalidate first. If * the block device is in use, we don't want to * do that as there may be I/Os bound for the disk * at the moment. In that case we read the size * from the device and update the information ourselves * and the user can later force a partition table * update through an ioctl. */ case I2O_EVT_IND_BSA_CAPACITY_CHANGE: { u64 size; if (i2ob_query_device(dev, 0x0004, 0, &size, 8) != 0) i2ob_query_device(dev, 0x0000, 4, &size, 8); spin_lock_irqsave(dev->req_queue->queue_lock, flags); set_capacity(dev->gendisk, size >> 9); spin_unlock_irqrestore(dev->req_queue-> queue_lock, flags); break; } /* * We got a SCSI SMART event, we just log the relevant * information and let the user decide what they want * to do with the information. */ case I2O_EVT_IND_BSA_SCSI_SMART: { char buf[16]; printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n", dev->i2o_device->dev_name); evt_local->data[16] = '\0'; sprintf(buf, "%s", &evt_local->data[0]); printk(KERN_INFO " Disk Serial#:%s\n", buf); printk(KERN_INFO " ASC 0x%02x \n", evt_local->ASC); printk(KERN_INFO " ASCQ 0x%02x \n", evt_local->ASCQ); break; } /* * Non event */ case 0: break; /* * An event we didn't ask for. Call the card manufacturer * and tell them to fix their firmware :) */ case 0x20: /* * If a promise card reports 0x20 event then the brown stuff * hit the fan big time. The card seems to recover but loses * the pending writes. Deeply ungood except for testing fsck */ if (dev->i2o_device->iop->promise) panic ("I2O controller firmware failed. Reboot and force a filesystem check.\n"); default: printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n" KERN_INFO " Blame the I2O card manufacturer 8)\n", dev->i2o_device->dev_name, evt); break; } }; complete_and_exit(&i2ob_thread_dead, 0); return 0;}#endif/* * SCSI-CAM for ioctl geometry mapping * Duplicated with SCSI - this should be moved into somewhere common * perhaps genhd ? * * LBA -> CHS mapping table taken from: * * "Incorporating the I2O Architecture into BIOS for Intel Architecture * Platforms" * * This is an I2O document that is only available to I2O members, * not developers. * * From my understanding, this is how all the I2O cards do this * * Disk Size | Sectors | Heads | Cylinders * ---------------+---------+-------+------------------- * 1 < X <= 528M | 63 | 16 | X/(63 * 16 * 512) * 528M < X <= 1G | 63 | 32 | X/(63 * 32 * 512) * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) * 1 < X <528M | 63 | 16 | X/(63 * 16 * 512) * */#define BLOCK_SIZE_528M 1081344#define BLOCK_SIZE_1G 2097152#define BLOCK_SIZE_21G 4403200#define BLOCK_SIZE_42G 8806400#define BLOCK_SIZE_84G 17612800static void i2o_block_biosparam(unsigned long capacity, unsigned short *cyls, unsigned char *hds, unsigned char *secs){ unsigned long heads, sectors, cylinders; sectors = 63L; /* Maximize sectors per track */ if (capacity <= BLOCK_SIZE_528M) heads = 16; else if (capacity <= BLOCK_SIZE_1G) heads = 32; else if (capacity <= BLOCK_SIZE_21G) heads = 64; else if (capacity <= BLOCK_SIZE_42G) heads = 128; else heads = 255; cylinders = (unsigned long)capacity / (heads * sectors); *cyls = (unsigned short)cylinders; /* Stuff return values */ *secs = (unsigned char)sectors; *hds = (unsigned char)heads;}/** * i2o_block_open - Open the block device * * Power up the device, mount and lock the media. This function is called, * if the block device is opened for access. * * Returns 0 on success or negative error code on failure. */static int i2o_block_open(struct inode *inode, struct file *file){ struct i2o_block_device *dev = inode->i_bdev->bd_disk->private_data; if (!dev->i2o_dev) return -ENODEV; if (dev->power > 0x1f) i2o_block_device_power(dev, 0x02); i2o_block_device_mount(dev->i2o_dev, -1); i2o_block_device_lock(dev->i2o_dev, -1); pr_debug("Ready.\n"); return 0;};/** * i2o_block_release - Release the I2O block device * * Unlock and unmount the media, and power down the device. Gets called if * the block device is closed. * * Returns 0 on success or negative error code on failure. */static int i2o_block_release(struct inode *inode, struct file *file){ struct gendisk *disk = inode->i_bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; u8 operation; /* * This is to deail with the case of an application * opening a device and then the device dissapears while * it's in use, and then the application tries to release * it. ex: Unmounting a deleted RAID volume at reboot. * If we send messages, it will just cause FAILs since * the TID no longer exists. */ if (!dev->i2o_dev) return 0; i2o_block_device_flush(dev->i2o_dev); i2o_block_device_unlock(dev->i2o_dev, -1); if (dev->flags & (1 << 3 | 1 << 4)) /* Removable */ operation = 0x21; else operation = 0x24; i2o_block_device_power(dev, operation); return 0;}/** * i2o_block_ioctl - Issue device specific ioctl calls. * @cmd: ioctl command * @arg: arg * * Handles ioctl request for the block device. * * Return 0 on success or negative error on failure. */static int i2o_block_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct gendisk *disk = inode->i_bdev->bd_disk; struct i2o_block_device *dev = disk->private_data; void __user *argp = (void __user *)arg; /* Anyone capable of this syscall can do *real bad* things */ if (!capable(CAP_SYS_ADMIN)) return -EPERM; switch (cmd) { case HDIO_GETGEO: { struct hd_geometry g; i2o_block_biosparam(get_capacity(disk), &g.cylinders, &g.heads, &g.sectors); g.start = get_start_sect(inode->i_bdev); return copy_to_user(argp, &g, sizeof(g)) ? -EFAULT : 0; } case BLKI2OGRSTRAT: return put_user(dev->rcache, (int __user *)arg); case BLKI2OGWSTRAT: return put_user(dev->wcache, (int __user *)arg); case BLKI2OSRSTRAT: if (arg < 0 || arg > CACHE_SMARTFETCH) return -EINVAL; dev->rcache = arg; break; case BLKI2OSWSTRAT: if (arg != 0 && (arg < CACHE_WRITETHROUGH || arg > CACHE_SMARTBACK)) return -EINVAL; dev->wcache = arg; break; } return -ENOTTY;};/** * i2o_block_media_changed - Have we seen a media change? * @disk: gendisk which should be verified * * Verifies if the media has changed. * * Returns 1 if the media was changed or 0 otherwise. */static int i2o_block_media_changed(struct gendisk *disk){ struct i2o_block_device *p = disk->private_data; if (p->media_change_flag) { p->media_change_flag = 0; return 1; } return 0;}/** * i2o_block_transfer - Transfer a request to/from the I2O controller * @req: the request which should be transfered * * This function converts the request into a I2O message. The necessary * DMA buffers are allocated and after everything is setup post the message * to the I2O controller. No cleanup is done by this function. It is done * on the interrupt side when the reply arrives. * * Return 0 on success or negative error code on failure. */static int i2o_block_transfer(struct request *req){ struct i2o_block_device *dev = req->rq_disk->private_data; struct i2o_controller *c = dev->i2o_dev->iop; int tid = dev->i2o_dev->lct_data.tid; struct i2o_message *msg;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?