summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/DAC960.c46
-rw-r--r--drivers/block/DAC960.h20
-rw-r--r--drivers/block/Kconfig27
-rw-r--r--drivers/block/acsi.c4
-rw-r--r--drivers/block/acsi_slm.c8
-rw-r--r--drivers/block/amiflop.c17
-rw-r--r--drivers/block/aoe/aoe.h32
-rw-r--r--drivers/block/aoe/aoeblk.c47
-rw-r--r--drivers/block/aoe/aoechr.c18
-rw-r--r--drivers/block/aoe/aoecmd.c307
-rw-r--r--drivers/block/aoe/aoedev.c54
-rw-r--r--drivers/block/aoe/aoemain.c10
-rw-r--r--drivers/block/aoe/aoenet.c9
-rw-r--r--drivers/block/ataflop.c4
-rw-r--r--drivers/block/cciss.c597
-rw-r--r--drivers/block/cciss.h9
-rw-r--r--drivers/block/cciss_cmd.h36
-rw-r--r--drivers/block/cciss_scsi.c2
-rw-r--r--drivers/block/cpqarray.c21
-rw-r--r--drivers/block/floppy.c18
-rw-r--r--drivers/block/loop.c255
-rw-r--r--drivers/block/nbd.c26
-rw-r--r--drivers/block/paride/aten.c4
-rw-r--r--drivers/block/paride/bpck.c4
-rw-r--r--drivers/block/paride/bpck6.c17
-rw-r--r--drivers/block/paride/comm.c4
-rw-r--r--drivers/block/paride/dstr.c4
-rw-r--r--drivers/block/paride/epat.c4
-rw-r--r--drivers/block/paride/epia.c4
-rw-r--r--drivers/block/paride/fit2.c4
-rw-r--r--drivers/block/paride/fit3.c4
-rw-r--r--drivers/block/paride/friq.c4
-rw-r--r--drivers/block/paride/frpw.c4
-rw-r--r--drivers/block/paride/jumbo70
-rw-r--r--drivers/block/paride/kbic.c14
-rw-r--r--drivers/block/paride/ktti.c4
-rw-r--r--drivers/block/paride/on20.c4
-rw-r--r--drivers/block/paride/on26.c4
-rw-r--r--drivers/block/paride/paride.c47
-rw-r--r--drivers/block/paride/paride.h4
-rw-r--r--drivers/block/paride/pcd.c8
-rw-r--r--drivers/block/paride/pd.c16
-rw-r--r--drivers/block/paride/pf.c8
-rw-r--r--drivers/block/paride/pg.c4
-rw-r--r--drivers/block/paride/pseudo.h10
-rw-r--r--drivers/block/paride/pt.c4
-rw-r--r--drivers/block/pktcdvd.c689
-rw-r--r--drivers/block/ps2esdi.c6
-rw-r--r--drivers/block/rd.c12
-rw-r--r--drivers/block/swim3.c16
-rw-r--r--drivers/block/swim_iop.c8
-rw-r--r--drivers/block/sx8.c9
-rw-r--r--drivers/block/ub.c52
-rw-r--r--drivers/block/umem.c5
-rw-r--r--drivers/block/viodasd.c49
-rw-r--r--drivers/block/xd.c7
-rw-r--r--drivers/block/xd.h3
-rw-r--r--drivers/block/z2ram.c28
58 files changed, 1751 insertions, 954 deletions
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index a360215dbce..8d81a3a64c0 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -324,13 +324,13 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
Command->Next = Controller->FreeCommands;
Controller->FreeCommands = Command;
Controller->Commands[CommandIdentifier-1] = Command;
- ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, SLAB_ATOMIC,
+ ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, GFP_ATOMIC,
&ScatterGatherDMA);
if (ScatterGatherCPU == NULL)
return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION");
if (RequestSensePool != NULL) {
- RequestSenseCPU = pci_pool_alloc(RequestSensePool, SLAB_ATOMIC,
+ RequestSenseCPU = pci_pool_alloc(RequestSensePool, GFP_ATOMIC,
&RequestSenseDMA);
if (RequestSenseCPU == NULL) {
pci_pool_free(ScatterGatherPool, ScatterGatherCPU,
@@ -770,7 +770,7 @@ static void DAC960_P_QueueCommand(DAC960_Command_T *Command)
static void DAC960_ExecuteCommand(DAC960_Command_T *Command)
{
DAC960_Controller_T *Controller = Command->Controller;
- DECLARE_COMPLETION(Completion);
+ DECLARE_COMPLETION_ONSTACK(Completion);
unsigned long flags;
Command->Completion = &Completion;
@@ -2698,8 +2698,7 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
{
struct DAC960_privdata *privdata =
(struct DAC960_privdata *)entry->driver_data;
- irqreturn_t (*InterruptHandler)(int, void *, struct pt_regs *) =
- privdata->InterruptHandler;
+ irq_handler_t InterruptHandler = privdata->InterruptHandler;
unsigned int MemoryWindowSize = privdata->MemoryWindowSize;
DAC960_Controller_T *Controller = NULL;
unsigned char DeviceFunction = PCI_Device->devfn;
@@ -3331,7 +3330,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_
Command->DmaDirection = PCI_DMA_TODEVICE;
Command->CommandType = DAC960_WriteCommand;
}
- Command->Completion = Request->waiting;
+ Command->Completion = Request->end_io_data;
Command->LogicalDriveNumber = (long)Request->rq_disk->private_data;
Command->BlockNumber = Request->sector;
Command->BlockCount = Request->nr_sectors;
@@ -5253,10 +5252,9 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
*/
static irqreturn_t DAC960_GEM_InterruptHandler(int IRQ_Channel,
- void *DeviceIdentifier,
- struct pt_regs *InterruptRegisters)
+ void *DeviceIdentifier)
{
- DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+ DAC960_Controller_T *Controller = DeviceIdentifier;
void __iomem *ControllerBaseAddress = Controller->BaseAddress;
DAC960_V2_StatusMailbox_T *NextStatusMailbox;
unsigned long flags;
@@ -5295,10 +5293,9 @@ static irqreturn_t DAC960_GEM_InterruptHandler(int IRQ_Channel,
*/
static irqreturn_t DAC960_BA_InterruptHandler(int IRQ_Channel,
- void *DeviceIdentifier,
- struct pt_regs *InterruptRegisters)
+ void *DeviceIdentifier)
{
- DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+ DAC960_Controller_T *Controller = DeviceIdentifier;
void __iomem *ControllerBaseAddress = Controller->BaseAddress;
DAC960_V2_StatusMailbox_T *NextStatusMailbox;
unsigned long flags;
@@ -5338,10 +5335,9 @@ static irqreturn_t DAC960_BA_InterruptHandler(int IRQ_Channel,
*/
static irqreturn_t DAC960_LP_InterruptHandler(int IRQ_Channel,
- void *DeviceIdentifier,
- struct pt_regs *InterruptRegisters)
+ void *DeviceIdentifier)
{
- DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+ DAC960_Controller_T *Controller = DeviceIdentifier;
void __iomem *ControllerBaseAddress = Controller->BaseAddress;
DAC960_V2_StatusMailbox_T *NextStatusMailbox;
unsigned long flags;
@@ -5381,10 +5377,9 @@ static irqreturn_t DAC960_LP_InterruptHandler(int IRQ_Channel,
*/
static irqreturn_t DAC960_LA_InterruptHandler(int IRQ_Channel,
- void *DeviceIdentifier,
- struct pt_regs *InterruptRegisters)
+ void *DeviceIdentifier)
{
- DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+ DAC960_Controller_T *Controller = DeviceIdentifier;
void __iomem *ControllerBaseAddress = Controller->BaseAddress;
DAC960_V1_StatusMailbox_T *NextStatusMailbox;
unsigned long flags;
@@ -5420,10 +5415,9 @@ static irqreturn_t DAC960_LA_InterruptHandler(int IRQ_Channel,
*/
static irqreturn_t DAC960_PG_InterruptHandler(int IRQ_Channel,
- void *DeviceIdentifier,
- struct pt_regs *InterruptRegisters)
+ void *DeviceIdentifier)
{
- DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+ DAC960_Controller_T *Controller = DeviceIdentifier;
void __iomem *ControllerBaseAddress = Controller->BaseAddress;
DAC960_V1_StatusMailbox_T *NextStatusMailbox;
unsigned long flags;
@@ -5459,10 +5453,9 @@ static irqreturn_t DAC960_PG_InterruptHandler(int IRQ_Channel,
*/
static irqreturn_t DAC960_PD_InterruptHandler(int IRQ_Channel,
- void *DeviceIdentifier,
- struct pt_regs *InterruptRegisters)
+ void *DeviceIdentifier)
{
- DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+ DAC960_Controller_T *Controller = DeviceIdentifier;
void __iomem *ControllerBaseAddress = Controller->BaseAddress;
unsigned long flags;
@@ -5498,10 +5491,9 @@ static irqreturn_t DAC960_PD_InterruptHandler(int IRQ_Channel,
*/
static irqreturn_t DAC960_P_InterruptHandler(int IRQ_Channel,
- void *DeviceIdentifier,
- struct pt_regs *InterruptRegisters)
+ void *DeviceIdentifier)
{
- DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
+ DAC960_Controller_T *Controller = DeviceIdentifier;
void __iomem *ControllerBaseAddress = Controller->BaseAddress;
unsigned long flags;
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index a82f37f749a..6148073532b 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -71,7 +71,7 @@
Define a Boolean data type.
*/
-typedef enum { false, true } __attribute__ ((packed)) boolean;
+typedef bool boolean;
/*
@@ -2175,7 +2175,7 @@ static char
struct DAC960_privdata {
DAC960_HardwareType_T HardwareType;
DAC960_FirmwareType_T FirmwareType;
- irqreturn_t (*InterruptHandler)(int, void *, struct pt_regs *);
+ irq_handler_t InterruptHandler;
unsigned int MemoryWindowSize;
};
@@ -4379,8 +4379,8 @@ static inline void DAC960_P_To_PD_TranslateEnquiry(void *Enquiry)
static inline void DAC960_P_To_PD_TranslateDeviceState(void *DeviceState)
{
memcpy(DeviceState + 2, DeviceState + 3, 1);
- memcpy(DeviceState + 4, DeviceState + 5, 2);
- memcpy(DeviceState + 6, DeviceState + 8, 4);
+ memmove(DeviceState + 4, DeviceState + 5, 2);
+ memmove(DeviceState + 6, DeviceState + 8, 4);
}
static inline
@@ -4412,12 +4412,12 @@ static void DAC960_FinalizeController(DAC960_Controller_T *);
static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *);
static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *);
static void DAC960_RequestFunction(struct request_queue *);
-static irqreturn_t DAC960_BA_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_LP_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_LA_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_PG_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_PD_InterruptHandler(int, void *, struct pt_regs *);
-static irqreturn_t DAC960_P_InterruptHandler(int, void *, struct pt_regs *);
+static irqreturn_t DAC960_BA_InterruptHandler(int, void *);
+static irqreturn_t DAC960_LP_InterruptHandler(int, void *);
+static irqreturn_t DAC960_LA_InterruptHandler(int, void *);
+static irqreturn_t DAC960_PG_InterruptHandler(int, void *);
+static irqreturn_t DAC960_PD_InterruptHandler(int, void *);
+static irqreturn_t DAC960_P_InterruptHandler(int, void *);
static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *);
static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *);
static void DAC960_MonitoringTimerFunction(unsigned long);
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index b5382cedf0c..ce9cfcb6071 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -2,6 +2,8 @@
# Block device driver configuration
#
+if BLOCK
+
menu "Block devices"
config BLK_DEV_FD
@@ -166,7 +168,8 @@ config BLK_CPQ_CISS_DA
config CISS_SCSI_TAPE
bool "SCSI tape drive support for Smart Array 5xxx"
- depends on BLK_CPQ_CISS_DA && SCSI && PROC_FS
+ depends on BLK_CPQ_CISS_DA && PROC_FS
+ depends on SCSI=y || SCSI=BLK_CPQ_CISS_DA
help
When enabled (Y), this option allows SCSI tape drives and SCSI medium
changers (tape robots) to be accessed via a Compaq 5xxx array
@@ -205,8 +208,7 @@ config BLK_DEV_UMEM
module will be called umem.
The umem driver has not yet been allocated a MAJOR number, so
- one is chosen dynamically. Use "devfs" or look in /proc/devices
- for the device number
+ one is chosen dynamically.
config BLK_DEV_UBD
bool "Virtual block device"
@@ -304,6 +306,7 @@ config BLK_DEV_LOOP
config BLK_DEV_CRYPTOLOOP
tristate "Cryptoloop Support"
select CRYPTO
+ select CRYPTO_CBC
depends on BLK_DEV_LOOP
---help---
Say Y here if you want to be able to use the ciphers that are
@@ -405,7 +408,7 @@ config BLK_DEV_RAM_BLOCKSIZE
depends on BLK_DEV_RAM
default "1024"
help
- The default value is 1024 kilobytes. PAGE_SIZE is a much more
+ The default value is 1024 bytes. PAGE_SIZE is a much more
efficient choice however. The default is kept to ensure initrd
setups function - apparently needed by the rd_load_image routine
that supposes the filesystem in the image uses a 1024 blocksize.
@@ -428,14 +431,18 @@ config CDROM_PKTCDVD
tristate "Packet writing on CD/DVD media"
depends on !UML
help
- If you have a CDROM drive that supports packet writing, say Y to
- include preliminary support. It should work with any MMC/Mt Fuji
- compliant ATAPI or SCSI drive, which is just about any newer CD
- writer.
+ If you have a CDROM/DVD drive that supports packet writing, say
+ Y to include support. It should work with any MMC/Mt Fuji
+ compliant ATAPI or SCSI drive, which is just about any newer
+ DVD/CD writer.
- Currently only writing to CD-RW, DVD-RW and DVD+RW discs is possible.
+ Currently only writing to CD-RW, DVD-RW, DVD+RW and DVDRAM discs
+ is possible.
DVD-RW disks must be in restricted overwrite mode.
+ See the file <file:Documentation/cdrom/packet-writing.txt>
+ for further information on the use of this driver.
+
To compile this driver as a module, choose M here: the
module will be called pktcdvd.
@@ -468,3 +475,5 @@ config ATA_OVER_ETH
devices like the Coraid EtherDrive (R) Storage Blade.
endmenu
+
+endif
diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c
index 0b80fbb8dbf..706cdc6a69e 100644
--- a/drivers/block/acsi.c
+++ b/drivers/block/acsi.c
@@ -346,7 +346,7 @@ static int acsicmd_dma( const char *cmd, char *buffer, int blocks, int
rwflag, int enable);
static int acsi_reqsense( char *buffer, int targ, int lun);
static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struct *aip);
-static irqreturn_t acsi_interrupt (int irq, void *data, struct pt_regs *fp);
+static irqreturn_t acsi_interrupt (int irq, void *data);
static void unexpected_acsi_interrupt( void );
static void bad_rw_intr( void );
static void read_intr( void );
@@ -726,7 +726,7 @@ static void acsi_print_error(const unsigned char *errblk, struct acsi_info_struc
*
*******************************************************************/
-static irqreturn_t acsi_interrupt(int irq, void *data, struct pt_regs *fp )
+static irqreturn_t acsi_interrupt(int irq, void *data )
{ void (*acsi_irq_handler)(void) = do_acsi;
diff --git a/drivers/block/acsi_slm.c b/drivers/block/acsi_slm.c
index 4030a8fd118..e04be94d195 100644
--- a/drivers/block/acsi_slm.c
+++ b/drivers/block/acsi_slm.c
@@ -246,7 +246,7 @@ static int slm_getstats( char *buffer, int device );
static ssize_t slm_read( struct file* file, char *buf, size_t count, loff_t
*ppos );
static void start_print( int device );
-static irqreturn_t slm_interrupt(int irc, void *data, struct pt_regs *fp);
+static irqreturn_t slm_interrupt(int irc, void *data);
static void slm_test_ready( unsigned long dummy );
static void set_dma_addr( unsigned long paddr );
static unsigned long get_dma_addr( void );
@@ -363,7 +363,7 @@ static ssize_t slm_read( struct file *file, char *buf, size_t count,
loff_t *ppos )
{
- struct inode *node = file->f_dentry->d_inode;
+ struct inode *node = file->f_path.dentry->d_inode;
unsigned long page;
int length;
int end;
@@ -452,7 +452,7 @@ static void start_print( int device )
/* Only called when an error happened or at the end of a page */
-static irqreturn_t slm_interrupt(int irc, void *data, struct pt_regs *fp)
+static irqreturn_t slm_interrupt(int irc, void *data)
{ unsigned long addr;
int stat;
@@ -618,7 +618,7 @@ static ssize_t slm_write( struct file *file, const char *buf, size_t count,
loff_t *ppos )
{
- struct inode *node = file->f_dentry->d_inode;
+ struct inode *node = file->f_path.dentry->d_inode;
int device = iminor(node);
int n, filled, w, h;
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c
index 2641597c654..5d656217153 100644
--- a/drivers/block/amiflop.c
+++ b/drivers/block/amiflop.c
@@ -209,7 +209,7 @@ static int fd_device[4] = { 0, 0, 0, 0 };
/* Milliseconds timer */
-static irqreturn_t ms_isr(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t ms_isr(int irq, void *dummy)
{
ms_busy = -1;
wake_up(&ms_wait);
@@ -560,7 +560,7 @@ static unsigned long fd_get_drive_id(int drive)
return (id);
}
-static irqreturn_t fd_block_done(int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t fd_block_done(int irq, void *dummy)
{
if (block_flag)
custom.dsklen = 0x4000;
@@ -1709,10 +1709,13 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)
return get_disk(unit[drive].gendisk);
}
-int __init amiga_floppy_init(void)
+static int __init amiga_floppy_init(void)
{
int i, ret;
+ if (!MACH_IS_AMIGA)
+ return -ENXIO;
+
if (!AMIGAHW_PRESENT(AMI_FLOPPY))
return -ENXIO;
@@ -1809,15 +1812,9 @@ out_blkdev:
return ret;
}
+module_init(amiga_floppy_init);
#ifdef MODULE
-int init_module(void)
-{
- if (!MACH_IS_AMIGA)
- return -ENXIO;
- return amiga_floppy_init();
-}
-
#if 0 /* not safe to unload */
void cleanup_module(void)
{
diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index 6eebcb7be97..2308e83e5f3 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 "22"
+/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */
+#define VERSION "32"
#define AOE_MAJOR 152
#define DEVICE_NAME "aoe"
@@ -65,7 +65,7 @@ struct aoe_atahdr {
struct aoe_cfghdr {
__be16 bufcnt;
__be16 fwver;
- unsigned char res;
+ unsigned char scnt;
unsigned char aoeccmd;
unsigned char cslen[2];
};
@@ -78,12 +78,14 @@ enum {
DEVFL_GDALLOC = (1<<4), /* need to alloc gendisk */
DEVFL_PAUSE = (1<<5),
DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */
+ DEVFL_MAXBCNT = (1<<7), /* d->maxbcnt is not changeable */
+ DEVFL_KICKME = (1<<8),
BUFFL_FAIL = 1,
};
enum {
- MAXATADATA = 1024,
+ DEFAULTBCNT = 2 * 512, /* 2 sectors */
NPERSHELF = 16, /* number of slots per shelf address */
FREETAG = -1,
MIN_BUFS = 8,
@@ -107,11 +109,9 @@ struct frame {
ulong waited;
struct buf *buf;
char *bufaddr;
- int writedatalen;
- int ndata;
-
- /* largest possible */
- unsigned char data[sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr)];
+ ulong bcnt;
+ sector_t lba;
+ struct sk_buff *skb;
};
struct aoedev {
@@ -121,9 +121,12 @@ struct aoedev {
ulong sysminor;
ulong aoemajor;
ulong aoeminor;
- ulong nopen; /* (bd_openers isn't available without sleeping) */
- ulong rttavg; /* round trip average of requests/responses */
+ u16 nopen; /* (bd_openers isn't available without sleeping) */
+ u16 lasttag; /* last tag sent */
+ u16 rttavg; /* round trip average of requests/responses */
+ u16 mintimer;
u16 fw_ver; /* version of blade's firmware */
+ u16 maxbcnt;
struct work_struct work;/* disk create work struct */
struct gendisk *gd;
request_queue_t blkq;
@@ -137,8 +140,8 @@ struct aoedev {
mempool_t *bufpool; /* for deadlock-free Buf allocation */
struct list_head bufq; /* queue of bios to work on */
struct buf *inprocess; /* the one we're currently working on */
- ulong lasttag; /* last tag sent */
- ulong nframes; /* number of frames below */
+ ushort lostjumbo;
+ ushort nframes; /* number of frames below */
struct frame *frames;
};
@@ -156,7 +159,8 @@ void aoecmd_work(struct aoedev *d);
void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor);
void aoecmd_ata_rsp(struct sk_buff *);
void aoecmd_cfg_rsp(struct sk_buff *);
-void aoecmd_sleepwork(void *vp);
+void aoecmd_sleepwork(struct work_struct *);
+struct sk_buff *new_skb(ulong);
int aoedev_init(void);
void aoedev_exit(void);
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 393b86a3dbf..478489c568a 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */
/*
* aoeblk.c
* block device routines
@@ -12,9 +12,8 @@
#include <linux/netdevice.h>
#include "aoe.h"
-static kmem_cache_t *buf_pool_cache;
+static struct kmem_cache *buf_pool_cache;
-/* add attributes for our block devices in sysfs */
static ssize_t aoedisk_show_state(struct gendisk * disk, char *page)
{
struct aoedev *d = disk->private_data;
@@ -64,21 +63,27 @@ static struct disk_attribute disk_attr_fwver = {
.show = aoedisk_show_fwver
};
-static void
+static struct attribute *aoe_attrs[] = {
+ &disk_attr_state.attr,
+ &disk_attr_mac.attr,
+ &disk_attr_netif.attr,
+ &disk_attr_fwver.attr,
+ NULL
+};
+
+static const struct attribute_group attr_group = {
+ .attrs = aoe_attrs,
+};
+
+static int
aoedisk_add_sysfs(struct aoedev *d)
{
- sysfs_create_file(&d->gd->kobj, &disk_attr_state.attr);
- sysfs_create_file(&d->gd->kobj, &disk_attr_mac.attr);
- sysfs_create_file(&d->gd->kobj, &disk_attr_netif.attr);
- sysfs_create_file(&d->gd->kobj, &disk_attr_fwver.attr);
+ return sysfs_create_group(&d->gd->kobj, &attr_group);
}
void
aoedisk_rm_sysfs(struct aoedev *d)
{
- sysfs_remove_link(&d->gd->kobj, "state");
- sysfs_remove_link(&d->gd->kobj, "mac");
- sysfs_remove_link(&d->gd->kobj, "netif");
- sysfs_remove_link(&d->gd->kobj, "firmware-version");
+ sysfs_remove_group(&d->gd->kobj, &attr_group);
}
static int
@@ -132,8 +137,7 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio)
d = bio->bi_bdev->bd_disk->private_data;
buf = mempool_alloc(d->bufpool, GFP_NOIO);
if (buf == NULL) {
- printk(KERN_INFO "aoe: aoeblk_make_request: buf allocation "
- "failure\n");
+ printk(KERN_INFO "aoe: buf allocation failure\n");
bio_endio(bio, bio->bi_size, -ENOMEM);
return 0;
}
@@ -143,14 +147,15 @@ aoeblk_make_request(request_queue_t *q, struct bio *bio)
buf->bio = bio;
buf->resid = bio->bi_size;
buf->sector = bio->bi_sector;
- buf->bv = buf->bio->bi_io_vec;
+ buf->bv = &bio->bi_io_vec[bio->bi_idx];
+ WARN_ON(buf->bv->bv_len == 0);
buf->bv_resid = buf->bv->bv_len;
buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset;
spin_lock_irqsave(&d->lock, flags);
if ((d->flags & DEVFL_UP) == 0) {
- printk(KERN_INFO "aoe: aoeblk_make_request: device %ld.%ld is not up\n",
+ printk(KERN_INFO "aoe: device %ld.%ld is not up\n",
d->aoemajor, d->aoeminor);
spin_unlock_irqrestore(&d->lock, flags);
mempool_free(buf, d->bufpool);
@@ -176,7 +181,7 @@ aoeblk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
struct aoedev *d = bdev->bd_disk->private_data;
if ((d->flags & DEVFL_UP) == 0) {
- printk(KERN_ERR "aoe: aoeblk_ioctl: disk not up\n");
+ printk(KERN_ERR "aoe: disk not up\n");
return -ENODEV;
}
@@ -203,8 +208,8 @@ aoeblk_gdalloc(void *vp)
gd = alloc_disk(AOE_PARTITIONS);
if (gd == NULL) {
- printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate disk "
- "structure for %ld.%ld\n", d->aoemajor, d->aoeminor);
+ printk(KERN_ERR "aoe: cannot allocate disk structure for %ld.%ld\n",
+ d->aoemajor, d->aoeminor);
spin_lock_irqsave(&d->lock, flags);
d->flags &= ~DEVFL_GDALLOC;
spin_unlock_irqrestore(&d->lock, flags);
@@ -213,8 +218,8 @@ aoeblk_gdalloc(void *vp)
d->bufpool = mempool_create_slab_pool(MIN_BUFS, buf_pool_cache);
if (d->bufpool == NULL) {
- printk(KERN_ERR "aoe: aoeblk_gdalloc: cannot allocate bufpool "
- "for %ld.%ld\n", d->aoemajor, d->aoeminor);
+ printk(KERN_ERR "aoe: cannot allocate bufpool for %ld.%ld\n",
+ d->aoemajor, d->aoeminor);
put_disk(gd);
spin_lock_irqsave(&d->lock, flags);
d->flags &= ~DEVFL_GDALLOC;
diff --git a/drivers/block/aoe/aoechr.c b/drivers/block/aoe/aoechr.c
index 1bc1cf9603f..e22b4c9520a 100644
--- a/drivers/block/aoe/aoechr.c
+++ b/drivers/block/aoe/aoechr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */
/*
* aoechr.c
* AoE character device driver
@@ -15,7 +15,6 @@ enum {
MINOR_INTERFACES,
MINOR_REVALIDATE,
MSGSZ = 2048,
- NARGS = 10,
NMSG = 100, /* message backlog to retain */
};
@@ -56,9 +55,8 @@ static int
interfaces(const char __user *str, size_t size)
{
if (set_aoe_iflist(str, size)) {
- printk(KERN_CRIT
- "%s: could not set interface list: %s\n",
- __FUNCTION__, "too many interfaces");
+ printk(KERN_ERR
+ "aoe: could not set interface list: too many interfaces\n");
return -EINVAL;
}
return 0;
@@ -81,8 +79,7 @@ revalidate(const char __user *str, size_t size)
/* should be e%d.%d format */
n = sscanf(buf, "e%d.%d", &major, &minor);
if (n != 2) {
- printk(KERN_ERR "aoe: %s: invalid device specification\n",
- __FUNCTION__);
+ printk(KERN_ERR "aoe: invalid device specification\n");
return -EINVAL;
}
d = aoedev_by_aoeaddr(major, minor);
@@ -90,6 +87,7 @@ revalidate(const char __user *str, size_t size)
return -EINVAL;
spin_lock_irqsave(&d->lock, flags);
+ d->flags &= ~DEVFL_MAXBCNT;
d->flags |= DEVFL_PAUSE;
spin_unlock_irqrestore(&d->lock, flags);
aoecmd_cfg(major, minor);
@@ -116,7 +114,7 @@ bail: spin_unlock_irqrestore(&emsgs_lock, flags);
mp = kmalloc(n, GFP_ATOMIC);
if (mp == NULL) {
- printk(KERN_CRIT "aoe: aoechr_error: allocation failure, len=%ld\n", n);
+ printk(KERN_ERR "aoe: allocation failure, len=%ld\n", n);
goto bail;
}
@@ -141,7 +139,7 @@ aoechr_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offp
switch ((unsigned long) filp->private_data) {
default:
- printk(KERN_INFO "aoe: aoechr_write: can't write to that file.\n");
+ printk(KERN_INFO "aoe: can't write to that file.\n");
break;
case MINOR_DISCOVER:
ret = discover();
@@ -250,7 +248,7 @@ aoechr_init(void)
n = register_chrdev(AOE_MAJOR, "aoechr", &aoe_fops);
if (n < 0) {
- printk(KERN_ERR "aoe: aoechr_init: can't register char device\n");
+ printk(KERN_ERR "aoe: can't register char device\n");
return n;
}
sema_init(&emsgs_sema, 0);
diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c
index 39da28d344f..97f7f535f41 100644
--- a/drivers/block/aoe/aoecmd.c
+++ b/drivers/block/aoe/aoecmd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */
/*
* aoecmd.c
* Filesystem request handling methods
@@ -15,17 +15,19 @@
#define TIMERTICK (HZ / 10)
#define MINTIMER (2 * TIMERTICK)
#define MAXTIMER (HZ << 1)
-#define MAXWAIT (60 * 3) /* After MAXWAIT seconds, give up and fail dev */
-static struct sk_buff *
-new_skb(struct net_device *if_dev, ulong len)
+static int aoe_deadsecs = 60 * 3;
+module_param(aoe_deadsecs, int, 0644);
+MODULE_PARM_DESC(aoe_deadsecs, "After aoe_deadsecs seconds, give up and fail dev.");
+
+struct sk_buff *
+new_skb(ulong len)
{
struct sk_buff *skb;
skb = alloc_skb(len, GFP_ATOMIC);
if (skb) {
skb->nh.raw = skb->mac.raw = skb->data;
- skb->dev = if_dev;
skb->protocol = __constant_htons(ETH_P_AOE);
skb->priority = 0;
skb_put(skb, len);
@@ -40,29 +42,6 @@ new_skb(struct net_device *if_dev, ulong len)
return skb;
}
-static struct sk_buff *
-skb_prepare(struct aoedev *d, struct frame *f)
-{
- struct sk_buff *skb;
- char *p;
-
- skb = new_skb(d->ifp, f->ndata + f->writedatalen);
- if (!skb) {
- printk(KERN_INFO "aoe: skb_prepare: failure to allocate skb\n");
- return NULL;
- }
-
- p = skb->mac.raw;
- memcpy(p, f->data, f->ndata);
-
- if (f->writedatalen) {
- p += sizeof(struct aoe_hdr) + sizeof(struct aoe_atahdr);
- memcpy(p, f->bufaddr, f->writedatalen);
- }
-
- return skb;
-}
-
static struct frame *
getframe(struct aoedev *d, int tag)
{
@@ -107,6 +86,17 @@ aoehdr_atainit(struct aoedev *d, struct aoe_hdr *h)
return host_tag;
}
+static inline void
+put_lba(struct aoe_atahdr *ah, sector_t lba)
+{
+ ah->lba0 = lba;
+ ah->lba1 = lba >>= 8;
+ ah->lba2 = lba >>= 8;
+ ah->lba3 = lba >>= 8;
+ ah->lba4 = lba >>= 8;
+ ah->lba5 = lba >>= 8;
+}
+
static void
aoecmd_ata_rw(struct aoedev *d, struct frame *f)
{
@@ -125,29 +115,27 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
sector = buf->sector;
bcnt = buf->bv_resid;
- if (bcnt > MAXATADATA)
- bcnt = MAXATADATA;
+ if (bcnt > d->maxbcnt)
+ bcnt = d->maxbcnt;
/* initialize the headers & frame */
- h = (struct aoe_hdr *) f->data;
+ skb = f->skb;
+ h = (struct aoe_hdr *) skb->mac.raw;
ah = (struct aoe_atahdr *) (h+1);
- f->ndata = sizeof *h + sizeof *ah;
- memset(h, 0, f->ndata);
+ skb->len = sizeof *h + sizeof *ah;
+ memset(h, 0, ETH_ZLEN);
f->tag = aoehdr_atainit(d, h);
f->waited = 0;
f->buf = buf;
f->bufaddr = buf->bufaddr;
+ f->bcnt = bcnt;
+ f->lba = sector;
/* set up ata header */
ah->scnt = bcnt >> 9;
- ah->lba0 = sector;
- ah->lba1 = sector >>= 8;
- ah->lba2 = sector >>= 8;
- ah->lba3 = sector >>= 8;
+ put_lba(ah, sector);
if (d->flags & DEVFL_EXT) {
ah->aflags |= AOEAFL_EXT;
- ah->lba4 = sector >>= 8;
- ah->lba5 = sector >>= 8;
} else {
extbit = 0;
ah->lba3 &= 0x0f;
@@ -155,11 +143,14 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
}
if (bio_data_dir(buf->bio) == WRITE) {
+ skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
+ offset_in_page(f->bufaddr), bcnt);
ah->aflags |= AOEAFL_WRITE;
- f->writedatalen = bcnt;
+ skb->len += bcnt;
+ skb->data_len = bcnt;
} else {
+ skb->len = ETH_ZLEN;
writebit = 0;
- f->writedatalen = 0;
}
ah->cmdstat = WIN_READ | writebit | extbit;
@@ -168,26 +159,27 @@ aoecmd_ata_rw(struct aoedev *d, struct frame *f)
buf->nframesout += 1;
buf->bufaddr += bcnt;
buf->bv_resid -= bcnt;
-/* printk(KERN_INFO "aoe: bv_resid=%ld\n", buf->bv_resid); */
+/* printk(KERN_DEBUG "aoe: bv_resid=%ld\n", buf->bv_resid); */
buf->resid -= bcnt;
buf->sector += bcnt >> 9;
if (buf->resid == 0) {
d->inprocess = NULL;
} else if (buf->bv_resid == 0) {
buf->bv++;
+ WARN_ON(buf->bv->bv_len == 0);
buf->bv_resid = buf->bv->bv_len;
buf->bufaddr = page_address(buf->bv->bv_page) + buf->bv->bv_offset;
}
- skb = skb_prepare(d, f);
- if (skb) {
- skb->next = NULL;
- if (d->sendq_hd)
- d->sendq_tl->next = skb;
- else
- d->sendq_hd = skb;
- d->sendq_tl = skb;
- }
+ skb->dev = d->ifp;
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (skb == NULL)
+ return;
+ if (d->sendq_hd)
+ d->sendq_tl->next = skb;
+ else
+ d->sendq_hd = skb;
+ d->sendq_tl = skb;
}
/* some callers cannot sleep, and they can call this function,
@@ -209,11 +201,12 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
if (!is_aoe_netif(ifp))
continue;
- skb = new_skb(ifp, sizeof *h + sizeof *ch);
+ skb = new_skb(sizeof *h + sizeof *ch);
if (skb == NULL) {
- printk(KERN_INFO "aoe: aoecmd_cfg: skb alloc failure\n");
+ printk(KERN_INFO "aoe: skb alloc failure\n");
continue;
}
+ skb->dev = ifp;
if (sl_tail == NULL)
sl_tail = skb;
h = (struct aoe_hdr *) skb->mac.raw;
@@ -237,6 +230,29 @@ aoecmd_cfg_pkts(ushort aoemajor, unsigned char aoeminor, struct sk_buff **tail)
return sl;
}
+static struct frame *
+freeframe(struct aoedev *d)
+{
+ struct frame *f, *e;
+ int n = 0;
+
+ f = d->frames;
+ e = f + d->nframes;
+ for (; f<e; f++) {
+ if (f->tag != FREETAG)
+ continue;
+ if (atomic_read(&skb_shinfo(f->skb)->dataref) == 1) {
+ skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0;
+ return f;
+ }
+ n++;
+ }
+ if (n == d->nframes) /* wait for network layer */
+ d->flags |= DEVFL_KICKME;
+
+ return NULL;
+}
+
/* enters with d->lock held */
void
aoecmd_work(struct aoedev *d)
@@ -252,7 +268,7 @@ aoecmd_work(struct aoedev *d)
}
loop:
- f = getframe(d, FREETAG);
+ f = freeframe(d);
if (f == NULL)
return;
if (d->inprocess == NULL) {
@@ -260,7 +276,7 @@ loop:
return;
buf = container_of(d->bufq.next, struct buf, bufs);
list_del(d->bufq.next);
-/*printk(KERN_INFO "aoecmd_work: bi_size=%ld\n", buf->bio->bi_size); */
+/*printk(KERN_DEBUG "aoe: bi_size=%ld\n", buf->bio->bi_size); */
d->inprocess = buf;
}
aoecmd_ata_rw(d, f);
@@ -272,6 +288,7 @@ rexmit(struct aoedev *d, struct frame *f)
{
struct sk_buff *skb;
struct aoe_hdr *h;
+ struct aoe_atahdr *ah;
char buf[128];
u32 n;
@@ -283,21 +300,41 @@ rexmit(struct aoedev *d, struct frame *f)
d->aoemajor, d->aoeminor, f->tag, jiffies, n);
aoechr_error(buf);
- h = (struct aoe_hdr *) f->data;
+ skb = f->skb;
+ h = (struct aoe_hdr *) skb->mac.raw;
+ ah = (struct aoe_atahdr *) (h+1);
f->tag = n;
h->tag = cpu_to_be32(n);
memcpy(h->dst, d->addr, sizeof h->dst);
memcpy(h->src, d->ifp->dev_addr, sizeof h->src);
- skb = skb_prepare(d, f);
- if (skb) {
- skb->next = NULL;
- if (d->sendq_hd)
- d->sendq_tl->next = skb;
- else
- d->sendq_hd = skb;
- d->sendq_tl = skb;
+ n = DEFAULTBCNT / 512;
+ if (ah->scnt > n) {
+ ah->scnt = n;
+ if (ah->aflags & AOEAFL_WRITE) {
+ skb_fill_page_desc(skb, 0, virt_to_page(f->bufaddr),
+ offset_in_page(f->bufaddr), DEFAULTBCNT);
+ skb->len = sizeof *h + sizeof *ah + DEFAULTBCNT;
+ skb->data_len = DEFAULTBCNT;
+ }
+ if (++d->lostjumbo > (d->nframes << 1))
+ if (d->maxbcnt != DEFAULTBCNT) {
+ printk(KERN_INFO "aoe: e%ld.%ld: too many lost jumbo on %s - using 1KB frames.\n",
+ d->aoemajor, d->aoeminor, d->ifp->name);
+ d->maxbcnt = DEFAULTBCNT;
+ d->flags |= DEVFL_MAXBCNT;
+ }
}
+
+ skb->dev = d->ifp;
+ skb = skb_clone(skb, GFP_ATOMIC);
+ if (skb == NULL)
+ return;
+ if (d->sendq_hd)
+ d->sendq_tl->next = skb;
+ else
+ d->sendq_hd = skb;
+ d->sendq_tl = skb;
}
static int
@@ -340,13 +377,17 @@ rexmit_timer(ulong vp)
if (f->tag != FREETAG && tsince(f->tag) >= timeout) {
n = f->waited += timeout;
n /= HZ;
- if (n > MAXWAIT) { /* waited too long. device failure. */
+ if (n > aoe_deadsecs) { /* waited too long for response */
aoedev_downdev(d);
break;
}
rexmit(d, f);
}
}
+ if (d->flags & DEVFL_KICKME) {
+ d->flags &= ~DEVFL_KICKME;
+ aoecmd_work(d);
+ }
sl = d->sendq_hd;
d->sendq_hd = d->sendq_tl = NULL;
@@ -367,9 +408,9 @@ rexmit_timer(ulong vp)
/* this function performs work that has been deferred until sleeping is OK
*/
void
-aoecmd_sleepwork(void *vp)
+aoecmd_sleepwork(struct work_struct *work)
{
- struct aoedev *d = (struct aoedev *) vp;
+ struct aoedev *d = container_of(work, struct aoedev, work);
if (d->flags & DEVFL_GDALLOC)
aoeblk_gdalloc(d);
@@ -431,8 +472,8 @@ ataid_complete(struct aoedev *d, unsigned char *id)
}
if (d->ssize != ssize)
- printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu "
- "sectors\n", (unsigned long long)mac_addr(d->addr),
+ printk(KERN_INFO "aoe: %012llx e%lu.%lu v%04x has %llu sectors\n",
+ (unsigned long long)mac_addr(d->addr),
d->aoemajor, d->aoeminor,
d->fw_ver, (long long)ssize);
d->ssize = ssize;
@@ -442,11 +483,9 @@ ataid_complete(struct aoedev *d, unsigned char *id)
d->flags |= DEVFL_NEWSIZE;
} else {
if (d->flags & DEVFL_GDALLOC) {
- printk(KERN_INFO "aoe: %s: %s e%lu.%lu, %s\n",
- __FUNCTION__,
- "can't schedule work for",
+ printk(KERN_ERR "aoe: can't schedule work for e%lu.%lu, %s\n",
d->aoemajor, d->aoeminor,
- "it's already on! (This really shouldn't happen).\n");
+ "it's already on! This shouldn't happen.\n");
return;
}
d->flags |= DEVFL_GDALLOC;
@@ -460,8 +499,15 @@ calc_rttavg(struct aoedev *d, int rtt)
register long n;
n = rtt;
- if (n < MINTIMER)
- n = MINTIMER;
+ if (n < 0) {
+ n = -rtt;
+ if (n < MINTIMER)
+ n = MINTIMER;
+ else if (n > MAXTIMER)
+ n = MAXTIMER;
+ d->mintimer += (n - d->mintimer) >> 1;
+ } else if (n < d->mintimer)
+ n = d->mintimer;
else if (n > MAXTIMER)
n = MAXTIMER;
@@ -474,7 +520,7 @@ void
aoecmd_ata_rsp(struct sk_buff *skb)
{
struct aoedev *d;
- struct aoe_hdr *hin;
+ struct aoe_hdr *hin, *hout;
struct aoe_atahdr *ahin, *ahout;
struct frame *f;
struct buf *buf;
@@ -497,8 +543,10 @@ aoecmd_ata_rsp(struct sk_buff *skb)
spin_lock_irqsave(&d->lock, flags);
- f = getframe(d, be32_to_cpu(hin->tag));
+ n = be32_to_cpu(hin->tag);
+ f = getframe(d, n);
if (f == NULL) {
+ calc_rttavg(d, -tsince(n));
spin_unlock_irqrestore(&d->lock, flags);
snprintf(ebuf, sizeof ebuf,
"%15s e%d.%d tag=%08x@%08lx\n",
@@ -514,26 +562,27 @@ aoecmd_ata_rsp(struct sk_buff *skb)
calc_rttavg(d, tsince(f->tag));
ahin = (struct aoe_atahdr *) (hin+1);
- ahout = (struct aoe_atahdr *) (f->data + sizeof(struct aoe_hdr));
+ hout = (struct aoe_hdr *) f->skb->mac.raw;
+ ahout = (struct aoe_atahdr *) (hout+1);
buf = f->buf;
if (ahout->cmdstat == WIN_IDENTIFY)
d->flags &= ~DEVFL_PAUSE;
if (ahin->cmdstat & 0xa9) { /* these bits cleared on success */
- printk(KERN_CRIT "aoe: aoecmd_ata_rsp: ata error cmd=%2.2Xh "
- "stat=%2.2Xh from e%ld.%ld\n",
+ printk(KERN_ERR
+ "aoe: ata error cmd=%2.2Xh stat=%2.2Xh from e%ld.%ld\n",
ahout->cmdstat, ahin->cmdstat,
d->aoemajor, d->aoeminor);
if (buf)
buf->flags |= BUFFL_FAIL;
} else {
+ n = ahout->scnt << 9;
switch (ahout->cmdstat) {
case WIN_READ:
case WIN_READ_EXT:
- n = ahout->scnt << 9;
if (skb->len - sizeof *hin - sizeof *ahin < n) {
- printk(KERN_CRIT "aoe: aoecmd_ata_rsp: runt "
- "ata data size in read. skb->len=%d\n",
+ printk(KERN_ERR
+ "aoe: runt data size in read. skb->len=%d\n",
skb->len);
/* fail frame f? just returning will rexmit. */
spin_unlock_irqrestore(&d->lock, flags);
@@ -542,22 +591,49 @@ aoecmd_ata_rsp(struct sk_buff *skb)
memcpy(f->bufaddr, ahin+1, n);
case WIN_WRITE:
case WIN_WRITE_EXT:
+ if (f->bcnt -= n) {
+ skb = f->skb;
+ f->bufaddr += n;
+ put_lba(ahout, f->lba += ahout->scnt);
+ n = f->bcnt;
+ if (n > DEFAULTBCNT)
+ n = DEFAULTBCNT;
+ ahout->scnt = n >> 9;
+ if (ahout->aflags & AOEAFL_WRITE) {
+ skb_fill_page_desc(skb, 0,
+ virt_to_page(f->bufaddr),
+ offset_in_page(f->bufaddr), n);
+ skb->len = sizeof *hout + sizeof *ahout + n;
+ skb->data_len = n;
+ }
+ f->tag = newtag(d);
+ hout->tag = cpu_to_be32(f->tag);
+ skb->dev = d->ifp;
+ skb = skb_clone(skb, GFP_ATOMIC);
+ spin_unlock_irqrestore(&d->lock, flags);
+ if (skb)
+ aoenet_xmit(skb);
+ return;
+ }
+ if (n > DEFAULTBCNT)
+ d->lostjumbo = 0;
break;
case WIN_IDENTIFY:
if (skb->len - sizeof *hin - sizeof *ahin < 512) {
- printk(KERN_INFO "aoe: aoecmd_ata_rsp: runt data size "
- "in ataid. skb->len=%d\n", skb->len);
+ printk(KERN_INFO
+ "aoe: runt data size in ataid. skb->len=%d\n",
+ skb->len);
spin_unlock_irqrestore(&d->lock, flags);
return;
}
ataid_complete(d, (char *) (ahin+1));
break;
default:
- printk(KERN_INFO "aoe: aoecmd_ata_rsp: unrecognized "
- "outbound ata command %2.2Xh for %d.%d\n",
- ahout->cmdstat,
- be16_to_cpu(hin->major),
- hin->minor);
+ printk(KERN_INFO
+ "aoe: unrecognized ata command %2.2Xh for %d.%d\n",
+ ahout->cmdstat,
+ be16_to_cpu(hin->major),
+ hin->minor);
}
}
@@ -612,33 +688,32 @@ aoecmd_ata_id(struct aoedev *d)
struct frame *f;
struct sk_buff *skb;
- f = getframe(d, FREETAG);
+ f = freeframe(d);
if (f == NULL) {
- printk(KERN_CRIT "aoe: aoecmd_ata_id: can't get a frame. "
- "This shouldn't happen.\n");
+ printk(KERN_ERR "aoe: can't get a frame. This shouldn't happen.\n");
return NULL;
}
/* initialize the headers & frame */
- h = (struct aoe_hdr *) f->data;
+ skb = f->skb;
+ h = (struct aoe_hdr *) skb->mac.raw;
ah = (struct aoe_atahdr *) (h+1);
- f->ndata = sizeof *h + sizeof *ah;
- memset(h, 0, f->ndata);
+ skb->len = ETH_ZLEN;
+ memset(h, 0, ETH_ZLEN);
f->tag = aoehdr_atainit(d, h);
f->waited = 0;
- f->writedatalen = 0;
/* set up ata header */
ah->scnt = 1;
ah->cmdstat = WIN_IDENTIFY;
ah->lba3 = 0xa0;
- skb = skb_prepare(d, f);
+ skb->dev = d->ifp;
d->rttavg = MAXTIMER;
d->timer.function = rexmit_timer;
- return skb;
+ return skb_clone(skb, GFP_ATOMIC);
}
void
@@ -648,9 +723,9 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
struct aoe_hdr *h;
struct aoe_cfghdr *ch;
ulong flags, sysminor, aoemajor;
- u16 bufcnt;
struct sk_buff *sl;
enum { MAXFRAMES = 16 };
+ u16 n;
h = (struct aoe_hdr *) skb->mac.raw;
ch = (struct aoe_cfghdr *) (h+1);
@@ -661,26 +736,25 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
*/
aoemajor = be16_to_cpu(h->major);
if (aoemajor == 0xfff) {
- printk(KERN_CRIT "aoe: aoecmd_cfg_rsp: Warning: shelf "
- "address is all ones. Check shelf dip switches\n");
+ printk(KERN_ERR "aoe: Warning: shelf address is all ones. "
+ "Check shelf dip switches.\n");
return;
}
sysminor = SYSMINOR(aoemajor, h->minor);
if (sysminor * AOE_PARTITIONS + AOE_PARTITIONS > MINORMASK) {
- printk(KERN_INFO
- "aoe: e%ld.%d: minor number too large\n",
+ printk(KERN_INFO "aoe: e%ld.%d: minor number too large\n",
aoemajor, (int) h->minor);
return;
}
- bufcnt = be16_to_cpu(ch->bufcnt);
- if (bufcnt > MAXFRAMES) /* keep it reasonable */
- bufcnt = MAXFRAMES;
+ n = be16_to_cpu(ch->bufcnt);
+ if (n > MAXFRAMES) /* keep it reasonable */
+ n = MAXFRAMES;
- d = aoedev_by_sysminor_m(sysminor, bufcnt);
+ d = aoedev_by_sysminor_m(sysminor, n);
if (d == NULL) {
- printk(KERN_INFO "aoe: aoecmd_cfg_rsp: device sysminor_m failure\n");
+ printk(KERN_INFO "aoe: device sysminor_m failure\n");
return;
}
@@ -689,6 +763,20 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
/* permit device to migrate mac and network interface */
d->ifp = skb->dev;
memcpy(d->addr, h->src, sizeof d->addr);
+ if (!(d->flags & DEVFL_MAXBCNT)) {
+ n = d->ifp->mtu;
+ n -= sizeof (struct aoe_hdr) + sizeof (struct aoe_atahdr);
+ n /= 512;
+ if (n > ch->scnt)
+ n = ch->scnt;
+ n = n ? n * 512 : DEFAULTBCNT;
+ if (n != d->maxbcnt) {
+ printk(KERN_INFO
+ "aoe: e%ld.%ld: setting %d byte data frames on %s\n",
+ d->aoemajor, d->aoeminor, n, d->ifp->name);
+ d->maxbcnt = n;
+ }
+ }
/* don't change users' perspective */
if (d->nopen && !(d->flags & DEVFL_PAUSE)) {
@@ -696,6 +784,7 @@ aoecmd_cfg_rsp(struct sk_buff *skb)
return;
}
d->flags |= DEVFL_PAUSE; /* force pause */
+ d->mintimer = MINTIMER;
d->fw_ver = be16_to_cpu(ch->fwver);
/* check for already outstanding ataid */
diff --git a/drivers/block/aoe/aoedev.c b/drivers/block/aoe/aoedev.c
index ed4258a62df..05a97197c91 100644
--- a/drivers/block/aoe/aoedev.c
+++ b/drivers/block/aoe/aoedev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */
/*
* aoedev.c
* AoE device utility functions; maintains device list.
@@ -20,11 +20,8 @@ aoedev_isbusy(struct aoedev *d)
f = d->frames;
e = f + d->nframes;
do {
- if (f->tag != FREETAG) {
- printk(KERN_DEBUG "aoe: %ld.%ld isbusy\n",
- d->aoemajor, d->aoeminor);
+ if (f->tag != FREETAG)
return 1;
- }
} while (++f < e);
return 0;
@@ -66,22 +63,32 @@ aoedev_newdev(ulong nframes)
struct frame *f, *e;
d = kzalloc(sizeof *d, GFP_ATOMIC);
- if (d == NULL)
- return NULL;
f = kcalloc(nframes, sizeof *f, GFP_ATOMIC);
- if (f == NULL) {
- kfree(d);
+ switch (!d || !f) {
+ case 0:
+ d->nframes = nframes;
+ d->frames = f;
+ e = f + nframes;
+ for (; f<e; f++) {
+ f->tag = FREETAG;
+ f->skb = new_skb(ETH_ZLEN);
+ if (!f->skb)
+ break;
+ }
+ if (f == e)
+ break;
+ while (f > d->frames) {
+ f--;
+ dev_kfree_skb(f->skb);
+ }
+ default:
+ if (f)
+ kfree(f);
+ if (d)
+ kfree(d);
return NULL;
}
-
- INIT_WORK(&d->work, aoecmd_sleepwork, d);
-
- d->nframes = nframes;
- d->frames = f;
- e = f + nframes;
- for (; f<e; f++)
- f->tag = FREETAG;
-
+ INIT_WORK(&d->work, aoecmd_sleepwork);
spin_lock_init(&d->lock);
init_timer(&d->timer);
d->timer.data = (ulong) d;
@@ -114,6 +121,7 @@ aoedev_downdev(struct aoedev *d)
mempool_free(buf, d->bufpool);
bio_endio(bio, bio->bi_size, -EIO);
}
+ skb_shinfo(f->skb)->nr_frags = f->skb->data_len = 0;
}
d->inprocess = NULL;
@@ -148,7 +156,7 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt)
d = aoedev_newdev(bufcnt);
if (d == NULL) {
spin_unlock_irqrestore(&devlist_lock, flags);
- printk(KERN_INFO "aoe: aoedev_set: aoedev_newdev failure.\n");
+ printk(KERN_INFO "aoe: aoedev_newdev failure.\n");
return NULL;
}
d->sysminor = sysminor;
@@ -163,11 +171,19 @@ aoedev_by_sysminor_m(ulong sysminor, ulong bufcnt)
static void
aoedev_freedev(struct aoedev *d)
{
+ struct frame *f, *e;
+
if (d->gd) {
aoedisk_rm_sysfs(d);
del_gendisk(d->gd);
put_disk(d->gd);
}
+ f = d->frames;
+ e = f + d->nframes;
+ for (; f<e; f++) {
+ skb_shinfo(f->skb)->nr_frags = 0;
+ dev_kfree_skb(f->skb);
+ }
kfree(d->frames);
if (d->bufpool)
mempool_destroy(d->bufpool);
diff --git a/drivers/block/aoe/aoemain.c b/drivers/block/aoe/aoemain.c
index de08491ebe6..a04b7d61329 100644
--- a/drivers/block/aoe/aoemain.c
+++ b/drivers/block/aoe/aoemain.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */
/*
* aoemain.c
* Module initialization routines, discover timer
@@ -84,13 +84,11 @@ aoe_init(void)
goto net_fail;
ret = register_blkdev(AOE_MAJOR, DEVICE_NAME);
if (ret < 0) {
- printk(KERN_ERR "aoe: aoeblk_init: can't register major\n");
+ printk(KERN_ERR "aoe: can't register major\n");
goto blkreg_fail;
}
- printk(KERN_INFO
- "aoe: aoe_init: AoE v%s initialised.\n",
- VERSION);
+ printk(KERN_INFO "aoe: AoE v%s initialised.\n", VERSION);
discover_timer(TINIT);
return 0;
@@ -103,7 +101,7 @@ aoe_init(void)
chr_fail:
aoedev_exit();
- printk(KERN_INFO "aoe: aoe_init: initialisation failure.\n");
+ printk(KERN_INFO "aoe: initialisation failure.\n");
return ret;
}
diff --git a/drivers/block/aoe/aoenet.c b/drivers/block/aoe/aoenet.c
index c1434ed1188..9626e0f5da9 100644
--- a/drivers/block/aoe/aoenet.c
+++ b/drivers/block/aoe/aoenet.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004 Coraid, Inc. See COPYING for GPL terms. */
+/* Copyright (c) 2006 Coraid, Inc. See COPYING for GPL terms. */
/*
* aoenet.c
* Ethernet portion of AoE driver
@@ -74,7 +74,7 @@ set_aoe_iflist(const char __user *user_str, size_t size)
return -EINVAL;
if (copy_from_user(aoe_iflist, user_str, size)) {
- printk(KERN_INFO "aoe: %s: copy from user failed\n", __FUNCTION__);
+ printk(KERN_INFO "aoe: copy from user failed\n");
return -EFAULT;
}
aoe_iflist[size] = 0x00;
@@ -132,8 +132,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
if (n > NECODES)
n = 0;
if (net_ratelimit())
- printk(KERN_ERR "aoe: aoenet_rcv: error packet from %d.%d; "
- "ecode=%d '%s'\n",
+ printk(KERN_ERR "aoe: error packet from %d.%d; ecode=%d '%s'\n",
be16_to_cpu(h->major), h->minor,
h->err, aoe_errlist[n]);
goto exit;
@@ -147,7 +146,7 @@ aoenet_rcv(struct sk_buff *skb, struct net_device *ifp, struct packet_type *pt,
aoecmd_cfg_rsp(skb);
break;
default:
- printk(KERN_INFO "aoe: aoenet_rcv: unknown cmd %d\n", h->cmd);
+ printk(KERN_INFO "aoe: unknown cmd %d\n", h->cmd);
}
exit:
dev_kfree_skb(skb);
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c
index c39650920bd..14d6b949275 100644
--- a/drivers/block/ataflop.c
+++ b/drivers/block/ataflop.c
@@ -342,7 +342,7 @@ static void fd_select_drive( int drive );
static void fd_deselect( void );
static void fd_motor_off_timer( unsigned long dummy );
static void check_change( unsigned long dummy );
-static irqreturn_t floppy_irq (int irq, void *dummy, struct pt_regs *fp);
+static irqreturn_t floppy_irq (int irq, void *dummy);
static void fd_error( void );
static int do_format(int drive, int type, struct atari_format_descr *desc);
static void do_fd_action( int drive );
@@ -573,7 +573,7 @@ static inline void copy_buffer(void *from, void *to)
static void (*FloppyIRQHandler)( int status ) = NULL;
-static irqreturn_t floppy_irq (int irq, void *dummy, struct pt_regs *fp)
+static irqreturn_t floppy_irq (int irq, void *dummy)
{
unsigned char status;
void (*handler)( int );
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 2cd3391ff87..ee159edb6b8 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -20,7 +20,6 @@
*
*/
-#include <linux/config.h> /* CONFIG_PROC_FS */
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/types.h>
@@ -48,14 +47,15 @@
#include <linux/completion.h>
#define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "HP CISS Driver (v 3.6.10)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,10)
+#define DRIVER_NAME "HP CISS Driver (v 3.6.14)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(3,6,14)
/* Embedded module documentation macros - see modules.h */
MODULE_AUTHOR("Hewlett-Packard Company");
-MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.10");
+MODULE_DESCRIPTION("Driver for HP Controller SA5xxx SA6xxx version 3.6.14");
MODULE_SUPPORTED_DEVICE("HP SA5i SA5i+ SA532 SA5300 SA5312 SA641 SA642 SA6400"
" SA6i P600 P800 P400 P400i E200 E200i E500");
+MODULE_VERSION("3.6.14");
MODULE_LICENSE("GPL");
#include "cciss_cmd.h"
@@ -82,7 +82,9 @@ static const struct pci_device_id cciss_pci_device_id[] = {
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3213},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3214},
{PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSD, 0x103C, 0x3215},
- {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3233},
+ {PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_CISSC, 0x103C, 0x3237},
+ {PCI_VENDOR_ID_HP, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
+ PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
{0,}
};
@@ -91,27 +93,29 @@ MODULE_DEVICE_TABLE(pci, cciss_pci_device_id);
/* board_id = Subsystem Device ID & Vendor ID
* product = Marketing Name for the board
* access = Address of the struct of function pointers
+ * nr_cmds = Number of commands supported by controller
*/
static struct board_type products[] = {
- {0x40700E11, "Smart Array 5300", &SA5_access},
- {0x40800E11, "Smart Array 5i", &SA5B_access},
- {0x40820E11, "Smart Array 532", &SA5B_access},
- {0x40830E11, "Smart Array 5312", &SA5B_access},
- {0x409A0E11, "Smart Array 641", &SA5_access},
- {0x409B0E11, "Smart Array 642", &SA5_access},
- {0x409C0E11, "Smart Array 6400", &SA5_access},
- {0x409D0E11, "Smart Array 6400 EM", &SA5_access},
- {0x40910E11, "Smart Array 6i", &SA5_access},
- {0x3225103C, "Smart Array P600", &SA5_access},
- {0x3223103C, "Smart Array P800", &SA5_access},
- {0x3234103C, "Smart Array P400", &SA5_access},
- {0x3235103C, "Smart Array P400i", &SA5_access},
- {0x3211103C, "Smart Array E200i", &SA5_access},
- {0x3212103C, "Smart Array E200", &SA5_access},
- {0x3213103C, "Smart Array E200i", &SA5_access},
- {0x3214103C, "Smart Array E200i", &SA5_access},
- {0x3215103C, "Smart Array E200i", &SA5_access},
- {0x3233103C, "Smart Array E500", &SA5_access},
+ {0x40700E11, "Smart Array 5300", &SA5_access, 512},
+ {0x40800E11, "Smart Array 5i", &SA5B_access, 512},
+ {0x40820E11, "Smart Array 532", &SA5B_access, 512},
+ {0x40830E11, "Smart Array 5312", &SA5B_access, 512},
+ {0x409A0E11, "Smart Array 641", &SA5_access, 512},
+ {0x409B0E11, "Smart Array 642", &SA5_access, 512},
+ {0x409C0E11, "Smart Array 6400", &SA5_access, 512},
+ {0x409D0E11, "Smart Array 6400 EM", &SA5_access, 512},
+ {0x40910E11, "Smart Array 6i", &SA5_access, 512},
+ {0x3225103C, "Smart Array P600", &SA5_access, 512},
+ {0x3223103C, "Smart Array P800", &SA5_access, 512},
+ {0x3234103C, "Smart Array P400", &SA5_access, 512},
+ {0x3235103C, "Smart Array P400i", &SA5_access, 512},
+ {0x3211103C, "Smart Array E200i", &SA5_access, 120},
+ {0x3212103C, "Smart Array E200", &SA5_access, 120},
+ {0x3213103C, "Smart Array E200i", &SA5_access, 120},
+ {0x3214103C, "Smart Array E200i", &SA5_access, 120},
+ {0x3215103C, "Smart Array E200i", &SA5_access, 120},
+ {0x3237103C, "Smart Array E500", &SA5_access, 512},
+ {0xFFFF103C, "Unknown Smart Array", &SA5_access, 120},
};
/* How long to wait (in milliseconds) for board to go into simple mode */
@@ -122,7 +126,6 @@ static struct board_type products[] = {
#define MAX_CMD_RETRIES 3
#define READ_AHEAD 1024
-#define NR_CMDS 384 /* #commands that can be outstanding */
#define MAX_CTLR 32
/* Originally cciss driver only supports 8 major numbers */
@@ -131,26 +134,25 @@ static struct board_type products[] = {
static ctlr_info_t *hba[MAX_CTLR];
static void do_cciss_request(request_queue_t *q);
-static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs);
+static irqreturn_t do_cciss_intr(int irq, void *dev_id);
static int cciss_open(struct inode *inode, struct file *filep);
static int cciss_release(struct inode *inode, struct file *filep);
static int cciss_ioctl(struct inode *inode, struct file *filep,
unsigned int cmd, unsigned long arg);
static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo);
-static int revalidate_allvol(ctlr_info_t *host);
static int cciss_revalidate(struct gendisk *disk);
static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk);
static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
int clear_all);
-static void cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
- int withirq, unsigned int *total_size,
- unsigned int *block_size);
-static void cciss_geometry_inquiry(int ctlr, int logvol, int withirq,
- unsigned int total_size,
- unsigned int block_size,
- InquiryData_struct *inq_buff,
+static void cciss_read_capacity(int ctlr, int logvol, int withirq,
+ sector_t *total_size, unsigned int *block_size);
+static void cciss_read_capacity_16(int ctlr, int logvol, int withirq,
+ sector_t *total_size, unsigned int *block_size);
+static void cciss_geometry_inquiry(int ctlr, int logvol,
+ int withirq, sector_t total_size,
+ unsigned int block_size, InquiryData_struct *inq_buff,
drive_info_struct *drv);
static void cciss_getgeometry(int cntl_num);
static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *,
@@ -266,6 +268,7 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
"Firmware Version: %c%c%c%c\n"
"IRQ: %d\n"
"Logical drives: %d\n"
+ "Max sectors: %d\n"
"Current Q depth: %d\n"
"Current # commands on controller: %d\n"
"Max Q depth since init: %d\n"
@@ -276,7 +279,9 @@ static int cciss_proc_get_info(char *buffer, char **start, off_t offset,
(unsigned long)h->board_id,
h->firm_ver[0], h->firm_ver[1], h->firm_ver[2],
h->firm_ver[3], (unsigned int)h->intr[SIMPLE_MODE_INT],
- h->num_luns, h->Qdepth, h->commands_outstanding,
+ h->num_luns,
+ h->cciss_max_sectors,
+ h->Qdepth, h->commands_outstanding,
h->maxQsinceinit, h->max_outstanding, h->maxSG);
pos += size;
@@ -401,8 +406,8 @@ static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool)
} else { /* get it out of the controllers pool */
do {
- i = find_first_zero_bit(h->cmd_pool_bits, NR_CMDS);
- if (i == NR_CMDS)
+ i = find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds);
+ if (i == h->nr_cmds)
return NULL;
} while (test_and_set_bit
(i & (BITS_PER_LONG - 1),
@@ -488,7 +493,7 @@ static int cciss_open(struct inode *inode, struct file *filep)
* but I'm already using way to many device nodes to claim another one
* for "raw controller".
*/
- if (drv->nr_blocks == 0) {
+ if (drv->heads == 0) {
if (iminor(inode) != 0) { /* not node 0? */
/* if not node 0 make sure it is a partition = 0 */
if (iminor(inode) & 0x0f) {
@@ -530,7 +535,7 @@ static int do_ioctl(struct file *f, unsigned cmd, unsigned long arg)
{
int ret;
lock_kernel();
- ret = cciss_ioctl(f->f_dentry->d_inode, f, cmd, arg);
+ ret = cciss_ioctl(f->f_path.dentry->d_inode, f, cmd, arg);
unlock_kernel();
return ret;
}
@@ -851,9 +856,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
}
case CCISS_REVALIDVOLS:
- if (bdev != bdev->bd_contains || drv != host->drv)
- return -ENXIO;
- return revalidate_allvol(host);
+ return rebuild_lun_table(host, NULL);
case CCISS_GETLUNINFO:{
LogvolInfo_struct luninfo;
@@ -879,7 +882,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
char *buff = NULL;
u64bit temp64;
unsigned long flags;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
if (!arg)
return -EINVAL;
@@ -997,7 +1000,7 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
BYTE sg_used = 0;
int status = 0;
int i;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
__u32 left;
__u32 sz;
BYTE __user *data_ptr;
@@ -1153,75 +1156,6 @@ static int cciss_ioctl(struct inode *inode, struct file *filep,
}
}
-/*
- * revalidate_allvol is for online array config utilities. After a
- * utility reconfigures the drives in the array, it can use this function
- * (through an ioctl) to make the driver zap any previous disk structs for
- * that controller and get new ones.
- *
- * Right now I'm using the getgeometry() function to do this, but this
- * function should probably be finer grained and allow you to revalidate one
- * particular logical volume (instead of all of them on a particular
- * controller).
- */
-static int revalidate_allvol(ctlr_info_t *host)
-{
- int ctlr = host->ctlr, i;
- unsigned long flags;
-
- spin_lock_irqsave(CCISS_LOCK(ctlr), flags);
- if (host->usage_count > 1) {
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
- printk(KERN_WARNING "cciss: Device busy for volume"
- " revalidation (usage=%d)\n", host->usage_count);
- return -EBUSY;
- }
- host->usage_count++;
- spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
-
- for (i = 0; i < NWD; i++) {
- struct gendisk *disk = host->gendisk[i];
- if (disk) {
- request_queue_t *q = disk->queue;
-
- if (disk->flags & GENHD_FL_UP)
- del_gendisk(disk);
- if (q)
- blk_cleanup_queue(q);
- }
- }
-
- /*
- * Set the partition and block size structures for all volumes
- * on this controller to zero. We will reread all of this data
- */
- memset(host->drv, 0, sizeof(drive_info_struct)
- * CISS_MAX_LUN);
- /*
- * Tell the array controller not to give us any interrupts while
- * we check the new geometry. Then turn interrupts back on when
- * we're done.
- */
- host->access.set_intr_mask(host, CCISS_INTR_OFF);
- cciss_getgeometry(ctlr);
- host->access.set_intr_mask(host, CCISS_INTR_ON);
-
- /* Loop through each real device */
- for (i = 0; i < NWD; i++) {
- struct gendisk *disk = host->gendisk[i];
- drive_info_struct *drv = &(host->drv[i]);
- /* we must register the controller even if no disks exist */
- /* this is for the online array utilities */
- if (!drv->heads && i)
- continue;
- blk_queue_hardsect_size(drv->queue, drv->block_size);
- set_capacity(disk, drv->nr_blocks);
- add_disk(disk);
- }
- host->usage_count--;
- return 0;
-}
-
static inline void complete_buffers(struct bio *bio, int status)
{
while (bio) {
@@ -1229,7 +1163,6 @@ static inline void complete_buffers(struct bio *bio, int status)
int nr_sectors = bio_sectors(bio);
bio->bi_next = NULL;
- blk_finished_io(len);
bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);
bio = xbh;
}
@@ -1245,7 +1178,7 @@ static void cciss_check_queues(ctlr_info_t *h)
* in case the interrupt we serviced was from an ioctl and did not
* free any new commands.
*/
- if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS)
+ if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) == h->nr_cmds)
return;
/* We have room on the queue for more commands. Now we need to queue
@@ -1264,7 +1197,7 @@ static void cciss_check_queues(ctlr_info_t *h)
/* check to see if we have maxed out the number of commands
* that can be placed on the queue.
*/
- if ((find_first_zero_bit(h->cmd_pool_bits, NR_CMDS)) == NR_CMDS) {
+ if ((find_first_zero_bit(h->cmd_pool_bits, h->nr_cmds)) == h->nr_cmds) {
if (curr_queue == start_queue) {
h->next_to_run =
(start_queue + 1) % (h->highest_lun + 1);
@@ -1302,6 +1235,12 @@ static void cciss_softirq_done(struct request *rq)
complete_buffers(rq->bio, rq->errors);
+ if (blk_fs_request(rq)) {
+ const int rw = rq_data_dir(rq);
+
+ disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors);
+ }
+
#ifdef CCISS_DEBUG
printk("Done with %p\n", rq);
#endif /* CCISS_DEBUG */
@@ -1326,10 +1265,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
{
ctlr_info_t *h = hba[ctlr];
struct gendisk *disk;
- ReadCapdata_struct *size_buff = NULL;
InquiryData_struct *inq_buff = NULL;
unsigned int block_size;
- unsigned int total_size;
+ sector_t total_size;
unsigned long flags = 0;
int ret = 0;
@@ -1348,15 +1286,25 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
return;
/* Get information about the disk and modify the driver structure */
- size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL)
- goto mem_msg;
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL)
goto mem_msg;
- cciss_read_capacity(ctlr, drv_index, size_buff, 1,
+ cciss_read_capacity(ctlr, drv_index, 1,
&total_size, &block_size);
+
+ /* total size = last LBA + 1 */
+ /* FFFFFFFF + 1 = 0, cannot have a logical volume of size 0 */
+ /* so we assume this volume this must be >2TB in size */
+ if (total_size == (__u32) 0) {
+ cciss_read_capacity_16(ctlr, drv_index, 1,
+ &total_size, &block_size);
+ h->cciss_read = CCISS_READ_16;
+ h->cciss_write = CCISS_WRITE_16;
+ } else {
+ h->cciss_read = CCISS_READ_10;
+ h->cciss_write = CCISS_WRITE_10;
+ }
cciss_geometry_inquiry(ctlr, drv_index, 1, total_size, block_size,
inq_buff, &h->drv[drv_index]);
@@ -1367,6 +1315,11 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
/* if it's the controller it's already added */
if (drv_index) {
disk->queue = blk_init_queue(do_cciss_request, &h->lock);
+ sprintf(disk->disk_name, "cciss/c%dd%d", ctlr, drv_index);
+ disk->major = h->major;
+ disk->first_minor = drv_index << NWD_SHIFT;
+ disk->fops = &cciss_fops;
+ disk->private_data = &h->drv[drv_index];
/* Set up queue information */
disk->queue->backing_dev_info.ra_pages = READ_AHEAD;
@@ -1378,7 +1331,7 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
/* This is a limit in the driver and could be eliminated. */
blk_queue_max_phys_segments(disk->queue, MAXSGENTRIES);
- blk_queue_max_sectors(disk->queue, 512);
+ blk_queue_max_sectors(disk->queue, h->cciss_max_sectors);
blk_queue_softirq_done(disk->queue, cciss_softirq_done);
@@ -1392,7 +1345,6 @@ static void cciss_update_drive_info(int ctlr, int drv_index)
}
freeret:
- kfree(size_buff);
kfree(inq_buff);
return;
mem_msg:
@@ -1446,11 +1398,6 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
/* Set busy_configuring flag for this operation */
spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags);
- if (h->num_luns >= CISS_MAX_LUN) {
- spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
- return -EINVAL;
- }
-
if (h->busy_configuring) {
spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags);
return -EBUSY;
@@ -1483,17 +1430,8 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
0, 0, TYPE_CMD);
if (return_code == IO_OK) {
- listlength |=
- (0xff & (unsigned int)(ld_buff->LUNListLength[0]))
- << 24;
- listlength |=
- (0xff & (unsigned int)(ld_buff->LUNListLength[1]))
- << 16;
- listlength |=
- (0xff & (unsigned int)(ld_buff->LUNListLength[2]))
- << 8;
- listlength |=
- 0xff & (unsigned int)(ld_buff->LUNListLength[3]);
+ listlength =
+ be32_to_cpu(*(__u32 *) ld_buff->LUNListLength);
} else { /* reading number of logical volumes failed */
printk(KERN_WARNING "cciss: report logical volume"
" command failed\n");
@@ -1544,6 +1482,14 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
if (drv_index == -1)
goto freeret;
+ /*Check if the gendisk needs to be allocated */
+ if (!h->gendisk[drv_index]){
+ h->gendisk[drv_index] = alloc_disk(1 << NWD_SHIFT);
+ if (!h->gendisk[drv_index]){
+ printk(KERN_ERR "cciss: could not allocate new disk %d\n", drv_index);
+ goto mem_msg;
+ }
+ }
}
h->drv[drv_index].LunID = lunid;
cciss_update_drive_info(ctlr, drv_index);
@@ -1581,6 +1527,7 @@ static int rebuild_lun_table(ctlr_info_t *h, struct gendisk *del_disk)
static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
int clear_all)
{
+ int i;
ctlr_info_t *h = get_host(disk);
if (!capable(CAP_SYS_RAWIO))
@@ -1604,9 +1551,35 @@ static int deregister_disk(struct gendisk *disk, drive_info_struct *drv,
del_gendisk(disk);
if (q) {
blk_cleanup_queue(q);
+ /* Set drv->queue to NULL so that we do not try
+ * to call blk_start_queue on this queue in the
+ * interrupt handler
+ */
drv->queue = NULL;
}
+ /* If clear_all is set then we are deleting the logical
+ * drive, not just refreshing its info. For drives
+ * other than disk 0 we will call put_disk. We do not
+ * do this for disk 0 as we need it to be able to
+ * configure the controller.
+ */
+ if (clear_all){
+ /* This isn't pretty, but we need to find the
+ * disk in our array and NULL our the pointer.
+ * This is so that we will call alloc_disk if
+ * this index is used again later.
+ */
+ for (i=0; i < CISS_MAX_LUN; i++){
+ if(h->gendisk[i] == disk){
+ h->gendisk[i] = NULL;
+ break;
+ }
+ }
+ put_disk(disk);
+ }
}
+ } else {
+ set_capacity(disk, 0);
}
--h->num_luns;
@@ -1717,6 +1690,22 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_
c->Request.Timeout = 0;
c->Request.CDB[0] = cmd;
break;
+ case CCISS_READ_CAPACITY_16:
+ c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID;
+ c->Header.LUN.LogDev.Mode = 1;
+ c->Request.CDBLen = 16;
+ c->Request.Type.Attribute = ATTR_SIMPLE;
+ c->Request.Type.Direction = XFER_READ;
+ c->Request.Timeout = 0;
+ c->Request.CDB[0] = cmd;
+ c->Request.CDB[1] = 0x10;
+ c->Request.CDB[10] = (size >> 24) & 0xFF;
+ c->Request.CDB[11] = (size >> 16) & 0xFF;
+ c->Request.CDB[12] = (size >> 8) & 0xFF;
+ c->Request.CDB[13] = size & 0xFF;
+ c->Request.Timeout = 0;
+ c->Request.CDB[0] = cmd;
+ break;
case CCISS_CACHE_FLUSH:
c->Request.CDBLen = 12;
c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1750,6 +1739,7 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_
memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB));
c->Request.CDB[0] = cmd; /* reset */
c->Request.CDB[1] = 0x04; /* reset a LUN */
+ break;
case 3: /* No-Op message */
c->Request.CDBLen = 1;
c->Request.Type.Attribute = ATTR_SIMPLE;
@@ -1792,7 +1782,7 @@ static int sendcmd_withirq(__u8 cmd,
u64bit buff_dma_handle;
unsigned long flags;
int return_status;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
if ((c = cmd_alloc(h, 0)) == NULL)
return -ENOMEM;
@@ -1893,12 +1883,14 @@ static int sendcmd_withirq(__u8 cmd,
}
static void cciss_geometry_inquiry(int ctlr, int logvol,
- int withirq, unsigned int total_size,
+ int withirq, sector_t total_size,
unsigned int block_size,
InquiryData_struct *inq_buff,
drive_info_struct *drv)
{
int return_code;
+ unsigned long t;
+
memset(inq_buff, 0, sizeof(InquiryData_struct));
if (withirq)
return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,
@@ -1913,59 +1905,98 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
printk(KERN_WARNING
"cciss: reading geometry failed, volume "
"does not support reading geometry\n");
- drv->block_size = block_size;
- drv->nr_blocks = total_size;
drv->heads = 255;
drv->sectors = 32; // Sectors per track
- drv->cylinders = total_size / 255 / 32;
} else {
- unsigned int t;
-
- drv->block_size = block_size;
- drv->nr_blocks = total_size;
drv->heads = inq_buff->data_byte[6];
drv->sectors = inq_buff->data_byte[7];
drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8;
drv->cylinders += inq_buff->data_byte[5];
drv->raid_level = inq_buff->data_byte[8];
- t = drv->heads * drv->sectors;
- if (t > 1) {
- drv->cylinders = total_size / t;
- }
+ }
+ drv->block_size = block_size;
+ drv->nr_blocks = total_size;
+ t = drv->heads * drv->sectors;
+ if (t > 1) {
+ unsigned rem = sector_div(total_size, t);
+ if (rem)
+ total_size++;
+ drv->cylinders = total_size;
}
} else { /* Get geometry failed */
printk(KERN_WARNING "cciss: reading geometry failed\n");
}
- printk(KERN_INFO " heads= %d, sectors= %d, cylinders= %d\n\n",
+ printk(KERN_INFO " heads=%d, sectors=%d, cylinders=%d\n\n",
drv->heads, drv->sectors, drv->cylinders);
}
static void
-cciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,
- int withirq, unsigned int *total_size,
+cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size,
unsigned int *block_size)
{
+ ReadCapdata_struct *buf;
int return_code;
- memset(buf, 0, sizeof(*buf));
+ buf = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
+ if (buf == NULL) {
+ printk(KERN_WARNING "cciss: out of memory\n");
+ return;
+ }
+ memset(buf, 0, sizeof(ReadCapdata_struct));
if (withirq)
return_code = sendcmd_withirq(CCISS_READ_CAPACITY,
- ctlr, buf, sizeof(*buf), 1,
- logvol, 0, TYPE_CMD);
+ ctlr, buf, sizeof(ReadCapdata_struct),
+ 1, logvol, 0, TYPE_CMD);
else
return_code = sendcmd(CCISS_READ_CAPACITY,
- ctlr, buf, sizeof(*buf), 1, logvol, 0,
- NULL, TYPE_CMD);
+ ctlr, buf, sizeof(ReadCapdata_struct),
+ 1, logvol, 0, NULL, TYPE_CMD);
if (return_code == IO_OK) {
- *total_size =
- be32_to_cpu(*((__be32 *) & buf->total_size[0])) + 1;
- *block_size = be32_to_cpu(*((__be32 *) & buf->block_size[0]));
+ *total_size = be32_to_cpu(*(__u32 *) buf->total_size)+1;
+ *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
} else { /* read capacity command failed */
printk(KERN_WARNING "cciss: read capacity failed\n");
*total_size = 0;
*block_size = BLOCK_SIZE;
}
- printk(KERN_INFO " blocks= %u block_size= %d\n",
- *total_size, *block_size);
+ if (*total_size != (__u32) 0)
+ printk(KERN_INFO " blocks= %llu block_size= %d\n",
+ (unsigned long long)*total_size, *block_size);
+ kfree(buf);
+ return;
+}
+
+static void
+cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, unsigned int *block_size)
+{
+ ReadCapdata_struct_16 *buf;
+ int return_code;
+ buf = kmalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL);
+ if (buf == NULL) {
+ printk(KERN_WARNING "cciss: out of memory\n");
+ return;
+ }
+ memset(buf, 0, sizeof(ReadCapdata_struct_16));
+ if (withirq) {
+ return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16,
+ ctlr, buf, sizeof(ReadCapdata_struct_16),
+ 1, logvol, 0, TYPE_CMD);
+ }
+ else {
+ return_code = sendcmd(CCISS_READ_CAPACITY_16,
+ ctlr, buf, sizeof(ReadCapdata_struct_16),
+ 1, logvol, 0, NULL, TYPE_CMD);
+ }
+ if (return_code == IO_OK) {
+ *total_size = be64_to_cpu(*(__u64 *) buf->total_size)+1;
+ *block_size = be32_to_cpu(*(__u32 *) buf->block_size);
+ } else { /* read capacity command failed */
+ printk(KERN_WARNING "cciss: read capacity failed\n");
+ *total_size = 0;
+ *block_size = BLOCK_SIZE;
+ }
+ printk(KERN_INFO " blocks= %llu block_size= %d\n",
+ (unsigned long long)*total_size, *block_size);
+ kfree(buf);
return;
}
@@ -1976,8 +2007,7 @@ static int cciss_revalidate(struct gendisk *disk)
int logvol;
int FOUND = 0;
unsigned int block_size;
- unsigned int total_size;
- ReadCapdata_struct *size_buff = NULL;
+ sector_t total_size;
InquiryData_struct *inq_buff = NULL;
for (logvol = 0; logvol < CISS_MAX_LUN; logvol++) {
@@ -1990,27 +2020,24 @@ static int cciss_revalidate(struct gendisk *disk)
if (!FOUND)
return 1;
- size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL) {
- printk(KERN_WARNING "cciss: out of memory\n");
- return 1;
- }
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_WARNING "cciss: out of memory\n");
- kfree(size_buff);
return 1;
}
-
- cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size,
- &block_size);
+ if (h->cciss_read == CCISS_READ_10) {
+ cciss_read_capacity(h->ctlr, logvol, 1,
+ &total_size, &block_size);
+ } else {
+ cciss_read_capacity_16(h->ctlr, logvol, 1,
+ &total_size, &block_size);
+ }
cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size,
inq_buff, drv);
blk_queue_hardsect_size(drv->queue, drv->block_size);
set_capacity(disk, drv->nr_blocks);
- kfree(size_buff);
kfree(inq_buff);
return 0;
}
@@ -2070,7 +2097,7 @@ static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete)
/* We've sent down an abort or reset, but something else
has completed */
- if (srl->ncompletions >= (NR_CMDS + 2)) {
+ if (srl->ncompletions >= (hba[ctlr]->nr_cmds + 2)) {
/* Uh oh. No room to save it for later... */
printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, "
"reject list overflow, command lost!\n", ctlr);
@@ -2236,7 +2263,7 @@ static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use
#ifdef CONFIG_CISS_SCSI_TAPE
/* if we saved some commands for later, process them now. */
if (info_p->scsi_rejects.ncompletions > 0)
- do_cciss_intr(0, info_p, NULL);
+ do_cciss_intr(0, info_p);
#endif
cmd_free(info_p, c, 1);
return status;
@@ -2419,7 +2446,8 @@ static void do_cciss_request(request_queue_t *q)
{
ctlr_info_t *h = q->queuedata;
CommandList_struct *c;
- int start_blk, seg;
+ sector_t start_blk;
+ int seg;
struct request *creq;
u64bit temp64;
struct scatterlist tmp_sg[MAXSGENTRIES];
@@ -2463,10 +2491,10 @@ static void do_cciss_request(request_queue_t *q)
c->Request.Type.Type = TYPE_CMD; // It is a command.
c->Request.Type.Attribute = ATTR_SIMPLE;
c->Request.Type.Direction =
- (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE;
+ (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
c->Request.Timeout = 0; // Don't time out
c->Request.CDB[0] =
- (rq_data_dir(creq) == READ) ? CCISS_READ : CCISS_WRITE;
+ (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
start_blk = creq->sector;
#ifdef CCISS_DEBUG
printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector,
@@ -2500,15 +2528,33 @@ static void do_cciss_request(request_queue_t *q)
#endif /* CCISS_DEBUG */
c->Header.SGList = c->Header.SGTotal = seg;
- c->Request.CDB[1] = 0;
- c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB
- c->Request.CDB[3] = (start_blk >> 16) & 0xff;
- c->Request.CDB[4] = (start_blk >> 8) & 0xff;
- c->Request.CDB[5] = start_blk & 0xff;
- c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB
- c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
- c->Request.CDB[8] = creq->nr_sectors & 0xff;
- c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
+ if(h->cciss_read == CCISS_READ_10) {
+ c->Request.CDB[1] = 0;
+ c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB
+ c->Request.CDB[3] = (start_blk >> 16) & 0xff;
+ c->Request.CDB[4] = (start_blk >> 8) & 0xff;
+ c->Request.CDB[5] = start_blk & 0xff;
+ c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB
+ c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff;
+ c->Request.CDB[8] = creq->nr_sectors & 0xff;
+ c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
+ } else {
+ c->Request.CDBLen = 16;
+ c->Request.CDB[1]= 0;
+ c->Request.CDB[2]= (start_blk >> 56) & 0xff; //MSB
+ c->Request.CDB[3]= (start_blk >> 48) & 0xff;
+ c->Request.CDB[4]= (start_blk >> 40) & 0xff;
+ c->Request.CDB[5]= (start_blk >> 32) & 0xff;
+ c->Request.CDB[6]= (start_blk >> 24) & 0xff;
+ c->Request.CDB[7]= (start_blk >> 16) & 0xff;
+ c->Request.CDB[8]= (start_blk >> 8) & 0xff;
+ c->Request.CDB[9]= start_blk & 0xff;
+ c->Request.CDB[10]= (creq->nr_sectors >> 24) & 0xff;
+ c->Request.CDB[11]= (creq->nr_sectors >> 16) & 0xff;
+ c->Request.CDB[12]= (creq->nr_sectors >> 8) & 0xff;
+ c->Request.CDB[13]= creq->nr_sectors & 0xff;
+ c->Request.CDB[14] = c->Request.CDB[15] = 0;
+ }
spin_lock_irq(q->queue_lock);
@@ -2518,9 +2564,9 @@ static void do_cciss_request(request_queue_t *q)
h->maxQsinceinit = h->Qdepth;
goto queue;
- full:
+full:
blk_stop_queue(q);
- startio:
+startio:
/* We will already have the driver lock here so not need
* to lock it.
*/
@@ -2569,7 +2615,7 @@ static inline long interrupt_not_for_us(ctlr_info_t *h)
#endif
}
-static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t do_cciss_intr(int irq, void *dev_id)
{
ctlr_info_t *h = dev_id;
CommandList_struct *c;
@@ -2588,7 +2634,7 @@ static irqreturn_t do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs)
a1 = a;
if ((a & 0x04)) {
a2 = (a >> 3);
- if (a2 >= NR_CMDS) {
+ if (a2 >= h->nr_cmds) {
printk(KERN_WARNING
"cciss: controller cciss%d failed, stopping.\n",
h->ctlr);
@@ -2742,23 +2788,21 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *c,
if (err > 0) {
printk(KERN_WARNING "cciss: only %d MSI-X vectors "
"available\n", err);
+ goto default_int_mode;
} else {
printk(KERN_WARNING "cciss: MSI-X init failed %d\n",
err);
+ goto default_int_mode;
}
}
if (pci_find_capability(pdev, PCI_CAP_ID_MSI)) {
if (!pci_enable_msi(pdev)) {
- c->intr[SIMPLE_MODE_INT] = pdev->irq;
c->msi_vector = 1;
- return;
} else {
printk(KERN_WARNING "cciss: MSI init failed\n");
- c->intr[SIMPLE_MODE_INT] = pdev->irq;
- return;
}
}
- default_int_mode:
+default_int_mode:
#endif /* CONFIG_PCI_MSI */
/* if we get here we're going to use the default interrupt mode */
c->intr[SIMPLE_MODE_INT] = pdev->irq;
@@ -2871,16 +2915,10 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
if (board_id == products[i].board_id) {
c->product_name = products[i].product_name;
c->access = *(products[i].access);
+ c->nr_cmds = products[i].nr_cmds;
break;
}
}
- if (i == ARRAY_SIZE(products)) {
- printk(KERN_WARNING "cciss: Sorry, I don't know how"
- " to access the Smart Array controller %08lx\n",
- (unsigned long)board_id);
- err = -ENODEV;
- goto err_out_free_res;
- }
if ((readb(&c->cfgtable->Signature[0]) != 'C') ||
(readb(&c->cfgtable->Signature[1]) != 'I') ||
(readb(&c->cfgtable->Signature[2]) != 'S') ||
@@ -2889,6 +2927,27 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
err = -ENODEV;
goto err_out_free_res;
}
+ /* We didn't find the controller in our list. We know the
+ * signature is valid. If it's an HP device let's try to
+ * bind to the device and fire it up. Otherwise we bail.
+ */
+ if (i == ARRAY_SIZE(products)) {
+ if (subsystem_vendor_id == PCI_VENDOR_ID_HP) {
+ c->product_name = products[i-1].product_name;
+ c->access = *(products[i-1].access);
+ c->nr_cmds = products[i-1].nr_cmds;
+ printk(KERN_WARNING "cciss: This is an unknown "
+ "Smart Array controller.\n"
+ "cciss: Please update to the latest driver "
+ "available from www.hp.com.\n");
+ } else {
+ printk(KERN_WARNING "cciss: Sorry, I don't know how"
+ " to access the Smart Array controller %08lx\n"
+ , (unsigned long)board_id);
+ err = -ENODEV;
+ goto err_out_free_res;
+ }
+ }
#ifdef CONFIG_X86
{
/* Need to enable prefetch in the SCSI core for 6400 in x86 */
@@ -2899,6 +2958,17 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
}
#endif
+ /* Disabling DMA prefetch for the P600
+ * An ASIC bug may result in a prefetch beyond
+ * physical memory.
+ */
+ if(board_id == 0x3225103C) {
+ __u32 dma_prefetch;
+ dma_prefetch = readl(c->vaddr + I2O_DMA1_CFG);
+ dma_prefetch |= 0x8000;
+ writel(dma_prefetch, c->vaddr + I2O_DMA1_CFG);
+ }
+
#ifdef CCISS_DEBUG
printk("Trying to put board into Simple mode\n");
#endif /* CCISS_DEBUG */
@@ -2948,31 +3018,23 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
static void cciss_getgeometry(int cntl_num)
{
ReportLunData_struct *ld_buff;
- ReadCapdata_struct *size_buff;
InquiryData_struct *inq_buff;
int return_code;
int i;
int listlength = 0;
__u32 lunid = 0;
int block_size;
- int total_size;
+ sector_t total_size;
ld_buff = kzalloc(sizeof(ReportLunData_struct), GFP_KERNEL);
if (ld_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
return;
}
- size_buff = kmalloc(sizeof(ReadCapdata_struct), GFP_KERNEL);
- if (size_buff == NULL) {
- printk(KERN_ERR "cciss: out of memory\n");
- kfree(ld_buff);
- return;
- }
inq_buff = kmalloc(sizeof(InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
- kfree(size_buff);
return;
}
/* Get the firmware version */
@@ -3027,7 +3089,6 @@ static void cciss_getgeometry(int cntl_num)
#endif /* CCISS_DEBUG */
hba[cntl_num]->highest_lun = hba[cntl_num]->num_luns - 1;
-// for(i=0; i< hba[cntl_num]->num_luns; i++)
for (i = 0; i < CISS_MAX_LUN; i++) {
if (i < hba[cntl_num]->num_luns) {
lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3]))
@@ -3046,8 +3107,26 @@ static void cciss_getgeometry(int cntl_num)
ld_buff->LUN[i][2], ld_buff->LUN[i][3],
hba[cntl_num]->drv[i].LunID);
#endif /* CCISS_DEBUG */
- cciss_read_capacity(cntl_num, i, size_buff, 0,
+
+ /* testing to see if 16-byte CDBs are already being used */
+ if(hba[cntl_num]->cciss_read == CCISS_READ_16) {
+ cciss_read_capacity_16(cntl_num, i, 0,
&total_size, &block_size);
+ goto geo_inq;
+ }
+ cciss_read_capacity(cntl_num, i, 0, &total_size, &block_size);
+
+ /* total_size = last LBA + 1 */
+ if(total_size == (__u32) 0) {
+ cciss_read_capacity_16(cntl_num, i, 0,
+ &total_size, &block_size);
+ hba[cntl_num]->cciss_read = CCISS_READ_16;
+ hba[cntl_num]->cciss_write = CCISS_WRITE_16;
+ } else {
+ hba[cntl_num]->cciss_read = CCISS_READ_10;
+ hba[cntl_num]->cciss_write = CCISS_WRITE_10;
+ }
+geo_inq:
cciss_geometry_inquiry(cntl_num, i, 0, total_size,
block_size, inq_buff,
&hba[cntl_num]->drv[i]);
@@ -3057,7 +3136,6 @@ static void cciss_getgeometry(int cntl_num)
}
}
kfree(ld_buff);
- kfree(size_buff);
kfree(inq_buff);
}
@@ -3065,13 +3143,7 @@ static void cciss_getgeometry(int cntl_num)
/* Returns -1 if no free entries are left. */
static int alloc_cciss_hba(void)
{
- struct gendisk *disk[NWD];
- int i, n;
- for (n = 0; n < NWD; n++) {
- disk[n] = alloc_disk(1 << NWD_SHIFT);
- if (!disk[n])
- goto out;
- }
+ int i;
for (i = 0; i < MAX_CTLR; i++) {
if (!hba[i]) {
@@ -3079,20 +3151,18 @@ static int alloc_cciss_hba(void)
p = kzalloc(sizeof(ctlr_info_t), GFP_KERNEL);
if (!p)
goto Enomem;
- for (n = 0; n < NWD; n++)
- p->gendisk[n] = disk[n];
+ p->gendisk[0] = alloc_disk(1 << NWD_SHIFT);
+ if (!p->gendisk[0])
+ goto Enomem;
hba[i] = p;
return i;
}
}
printk(KERN_WARNING "cciss: This driver supports a maximum"
" of %d controllers.\n", MAX_CTLR);
- goto out;
- Enomem:
+ return -1;
+Enomem:
printk(KERN_ERR "cciss: out of memory.\n");
- out:
- while (n--)
- put_disk(disk[n]);
return -1;
}
@@ -3102,7 +3172,7 @@ static void free_hba(int i)
int n;
hba[i] = NULL;
- for (n = 0; n < NWD; n++)
+ for (n = 0; n < CISS_MAX_LUN; n++)
put_disk(p->gendisk[n]);
kfree(p);
}
@@ -3115,9 +3185,8 @@ static void free_hba(int i)
static int __devinit cciss_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- request_queue_t *q;
int i;
- int j;
+ int j = 0;
int rc;
int dac;
@@ -3176,15 +3245,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->intr[SIMPLE_MODE_INT], dac ? "" : " not");
hba[i]->cmd_pool_bits =
- kmalloc(((NR_CMDS + BITS_PER_LONG -
+ kmalloc(((hba[i]->nr_cmds + BITS_PER_LONG -
1) / BITS_PER_LONG) * sizeof(unsigned long), GFP_KERNEL);
hba[i]->cmd_pool = (CommandList_struct *)
pci_alloc_consistent(hba[i]->pdev,
- NR_CMDS * sizeof(CommandList_struct),
+ hba[i]->nr_cmds * sizeof(CommandList_struct),
&(hba[i]->cmd_pool_dhandle));
hba[i]->errinfo_pool = (ErrorInfo_struct *)
pci_alloc_consistent(hba[i]->pdev,
- NR_CMDS * sizeof(ErrorInfo_struct),
+ hba[i]->nr_cmds * sizeof(ErrorInfo_struct),
&(hba[i]->errinfo_pool_dhandle));
if ((hba[i]->cmd_pool_bits == NULL)
|| (hba[i]->cmd_pool == NULL)
@@ -3195,7 +3264,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
#ifdef CONFIG_CISS_SCSI_TAPE
hba[i]->scsi_rejects.complete =
kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) *
- (NR_CMDS + 5), GFP_KERNEL);
+ (hba[i]->nr_cmds + 5), GFP_KERNEL);
if (hba[i]->scsi_rejects.complete == NULL) {
printk(KERN_ERR "cciss: out of memory");
goto clean4;
@@ -3209,7 +3278,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
/* command and error info recs zeroed out before
they are used */
memset(hba[i]->cmd_pool_bits, 0,
- ((NR_CMDS + BITS_PER_LONG -
+ ((hba[i]->nr_cmds + BITS_PER_LONG -
1) / BITS_PER_LONG) * sizeof(unsigned long));
#ifdef CCISS_DEBUG
@@ -3224,18 +3293,34 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
cciss_procinit(i);
+
+ hba[i]->cciss_max_sectors = 2048;
+
hba[i]->busy_initializing = 0;
- for (j = 0; j < NWD; j++) { /* mfm */
+ do {
drive_info_struct *drv = &(hba[i]->drv[j]);
struct gendisk *disk = hba[i]->gendisk[j];
+ request_queue_t *q;
+
+ /* Check if the disk was allocated already */
+ if (!disk){
+ hba[i]->gendisk[j] = alloc_disk(1 << NWD_SHIFT);
+ disk = hba[i]->gendisk[j];
+ }
+
+ /* Check that the disk was able to be allocated */
+ if (!disk) {
+ printk(KERN_ERR "cciss: unable to allocate memory for disk %d\n", j);
+ goto clean4;
+ }
q = blk_init_queue(do_cciss_request, &hba[i]->lock);
if (!q) {
printk(KERN_ERR
"cciss: unable to allocate queue for disk %d\n",
j);
- break;
+ goto clean4;
}
drv->queue = q;
@@ -3248,7 +3333,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
/* This is a limit in the driver and could be eliminated. */
blk_queue_max_phys_segments(q, MAXSGENTRIES);
- blk_queue_max_sectors(q, 512);
+ blk_queue_max_sectors(q, hba[i]->cciss_max_sectors);
blk_queue_softirq_done(q, cciss_softirq_done);
@@ -3267,7 +3352,8 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
blk_queue_hardsect_size(q, drv->block_size);
set_capacity(disk, drv->nr_blocks);
add_disk(disk);
- }
+ j++;
+ } while (j <= hba[i]->highest_lun);
return 1;
@@ -3278,11 +3364,11 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
kfree(hba[i]->cmd_pool_bits);
if (hba[i]->cmd_pool)
pci_free_consistent(hba[i]->pdev,
- NR_CMDS * sizeof(CommandList_struct),
+ hba[i]->nr_cmds * sizeof(CommandList_struct),
hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
if (hba[i]->errinfo_pool)
pci_free_consistent(hba[i]->pdev,
- NR_CMDS * sizeof(ErrorInfo_struct),
+ hba[i]->nr_cmds * sizeof(ErrorInfo_struct),
hba[i]->errinfo_pool,
hba[i]->errinfo_pool_dhandle);
free_irq(hba[i]->intr[SIMPLE_MODE_INT], hba[i]);
@@ -3290,6 +3376,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
unregister_blkdev(hba[i]->major, hba[i]->devname);
clean1:
hba[i]->busy_initializing = 0;
+ /* cleanup any queues that may have been initialized */
+ for (j=0; j <= hba[i]->highest_lun; j++){
+ drive_info_struct *drv = &(hba[i]->drv[j]);
+ if (drv->queue)
+ blk_cleanup_queue(drv->queue);
+ }
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
free_hba(i);
return -1;
}
@@ -3337,7 +3432,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
remove_proc_entry(hba[i]->devname, proc_cciss);
/* remove it from the disk list */
- for (j = 0; j < NWD; j++) {
+ for (j = 0; j < CISS_MAX_LUN; j++) {
struct gendisk *disk = hba[i]->gendisk[j];
if (disk) {
request_queue_t *q = disk->queue;
@@ -3349,9 +3444,9 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
}
}
- pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(CommandList_struct),
+ pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(CommandList_struct),
hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);
- pci_free_consistent(hba[i]->pdev, NR_CMDS * sizeof(ErrorInfo_struct),
+ pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(ErrorInfo_struct),
hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle);
kfree(hba[i]->cmd_pool_bits);
#ifdef CONFIG_CISS_SCSI_TAPE
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h
index 868e0d862b0..b70988dd33e 100644
--- a/drivers/block/cciss.h
+++ b/drivers/block/cciss.h
@@ -6,7 +6,6 @@
#include "cciss_cmd.h"
-#define NWD 16
#define NWD_SHIFT 4
#define MAX_PART (1 << NWD_SHIFT)
@@ -60,6 +59,7 @@ struct ctlr_info
__u32 board_id;
void __iomem *vaddr;
unsigned long paddr;
+ int nr_cmds; /* Number of commands allowed on this controller */
CfgTable_struct __iomem *cfgtable;
int interrupts_enabled;
int major;
@@ -76,6 +76,10 @@ struct ctlr_info
unsigned int intr[4];
unsigned int msix_vector;
unsigned int msi_vector;
+ int cciss_max_sectors;
+ BYTE cciss_read;
+ BYTE cciss_write;
+ BYTE cciss_read_capacity;
// information about each logical volume
drive_info_struct drv[CISS_MAX_LUN];
@@ -107,7 +111,7 @@ struct ctlr_info
int next_to_run;
// Disk structures we need to pass back
- struct gendisk *gendisk[NWD];
+ struct gendisk *gendisk[CISS_MAX_LUN];
#ifdef CONFIG_CISS_SCSI_TAPE
void *scsi_ctlr; /* ptr to structure containing scsi related stuff */
/* list of block side commands the scsi error handling sucked up */
@@ -279,6 +283,7 @@ struct board_type {
__u32 board_id;
char *product_name;
struct access_method *access;
+ int nr_cmds; /* Max cmds this kind of ctlr can handle. */
};
#define CCISS_LOCK(i) (&hba[i]->lock)
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h
index 53fea549ba8..43bf5593b59 100644
--- a/drivers/block/cciss_cmd.h
+++ b/drivers/block/cciss_cmd.h
@@ -55,6 +55,7 @@
#define I2O_INT_MASK 0x34
#define I2O_IBPOST_Q 0x40
#define I2O_OBPOST_Q 0x44
+#define I2O_DMA1_CFG 0x214
//Configuration Table
#define CFGTBL_ChangeReq 0x00000001l
@@ -88,7 +89,7 @@ typedef union _u64bit
//###########################################################################
//STRUCTURES
//###########################################################################
-#define CISS_MAX_LUN 16
+#define CISS_MAX_LUN 1024
#define CISS_MAX_PHYS_LUN 1024
// SCSI-3 Cmmands
@@ -118,11 +119,34 @@ typedef struct _ReadCapdata_struct
BYTE block_size[4]; // Size of blocks in bytes
} ReadCapdata_struct;
-// 12 byte commands not implemented in firmware yet.
-// #define CCISS_READ 0xa8 // Read(12)
-// #define CCISS_WRITE 0xaa // Write(12)
- #define CCISS_READ 0x28 // Read(10)
- #define CCISS_WRITE 0x2a // Write(10)
+#define CCISS_READ_CAPACITY_16 0x9e /* Read Capacity 16 */
+
+/* service action to differentiate a 16 byte read capacity from
+ other commands that use the 0x9e SCSI op code */
+
+#define CCISS_READ_CAPACITY_16_SERVICE_ACT 0x10
+
+typedef struct _ReadCapdata_struct_16
+{
+ BYTE total_size[8]; /* Total size in blocks */
+ BYTE block_size[4]; /* Size of blocks in bytes */
+ BYTE prot_en:1; /* protection enable bit */
+ BYTE rto_en:1; /* reference tag own enable bit */
+ BYTE reserved:6; /* reserved bits */
+ BYTE reserved2[18]; /* reserved bytes per spec */
+} ReadCapdata_struct_16;
+
+/* Define the supported read/write commands for cciss based controllers */
+
+#define CCISS_READ_10 0x28 /* Read(10) */
+#define CCISS_WRITE_10 0x2a /* Write(10) */
+#define CCISS_READ_16 0x88 /* Read(16) */
+#define CCISS_WRITE_16 0x8a /* Write(16) */
+
+/* Define the CDB lengths supported by cciss based controllers */
+
+#define CDB_LEN10 10
+#define CDB_LEN16 16
// BMIC commands
#define BMIC_READ 0x26
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c
index 05f79d7393f..bb15051ffbe 100644
--- a/drivers/block/cciss_scsi.c
+++ b/drivers/block/cciss_scsi.c
@@ -766,7 +766,7 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c,
int direction)
{
unsigned long flags;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
cp->cmd_type = CMD_IOCTL_PEND; // treat this like an ioctl
cp->scsi_cmd = NULL;
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c
index 78082edc14b..d5f519ebbc0 100644
--- a/drivers/block/cpqarray.c
+++ b/drivers/block/cpqarray.c
@@ -19,7 +19,6 @@
* Questions/Comments/Bugfixes to iss_storagedev@hp.com
*
*/
-#include <linux/config.h> /* CONFIG_PROC_FS */
#include <linux/module.h>
#include <linux/types.h>
#include <linux/pci.h>
@@ -170,7 +169,7 @@ static inline cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *c);
static inline void complete_buffers(struct bio *bio, int ok);
static inline void complete_command(cmdlist_t *cmd, int timeout);
-static irqreturn_t do_ida_intr(int irq, void *dev_id, struct pt_regs * regs);
+static irqreturn_t do_ida_intr(int irq, void *dev_id);
static void ida_timer(unsigned long tdata);
static int ida_revalidate(struct gendisk *disk);
static int revalidate_allvol(ctlr_info_t *host);
@@ -989,7 +988,6 @@ static inline void complete_buffers(struct bio *bio, int ok)
xbh = bio->bi_next;
bio->bi_next = NULL;
- blk_finished_io(nr_sectors);
bio_endio(bio, nr_sectors << 9, ok ? 0 : -EIO);
bio = xbh;
@@ -1000,6 +998,7 @@ static inline void complete_buffers(struct bio *bio, int ok)
*/
static inline void complete_command(cmdlist_t *cmd, int timeout)
{
+ struct request *rq = cmd->rq;
int ok=1;
int i, ddir;
@@ -1031,12 +1030,18 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
pci_unmap_page(hba[cmd->ctlr]->pci_dev, cmd->req.sg[i].addr,
cmd->req.sg[i].size, ddir);
- complete_buffers(cmd->rq->bio, ok);
+ complete_buffers(rq->bio, ok);
- add_disk_randomness(cmd->rq->rq_disk);
+ if (blk_fs_request(rq)) {
+ const int rw = rq_data_dir(rq);
- DBGPX(printk("Done with %p\n", cmd->rq););
- end_that_request_last(cmd->rq, ok ? 1 : -EIO);
+ disk_stat_add(rq->rq_disk, sectors[rw], rq->nr_sectors);
+ }
+
+ add_disk_randomness(rq->rq_disk);
+
+ DBGPX(printk("Done with %p\n", rq););
+ end_that_request_last(rq, ok ? 1 : -EIO);
}
/*
@@ -1044,7 +1049,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout)
* Find the command on the completion queue, remove it, tell the OS and
* try to queue up more IO
*/
-static irqreturn_t do_ida_intr(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t do_ida_intr(int irq, void *dev_id)
{
ctlr_info_t *h = dev_id;
cmdlist_t *c;
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index ad1d7065a1b..3f1b38276e9 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -221,7 +221,7 @@ static DEFINE_SPINLOCK(floppy_lock);
static struct completion device_release;
static unsigned short virtual_dma_port = 0x3f0;
-irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+irqreturn_t floppy_interrupt(int irq, void *dev_id);
static int set_dor(int fdc, char mask, char data);
#define K_64 0x10000 /* 64KB */
@@ -992,11 +992,11 @@ static void empty(void)
{
}
-static DECLARE_WORK(floppy_work, NULL, NULL);
+static DECLARE_WORK(floppy_work, NULL);
static void schedule_bh(void (*handler) (void))
{
- PREPARE_WORK(&floppy_work, (void (*)(void *))handler, NULL);
+ PREPARE_WORK(&floppy_work, (work_func_t)handler);
schedule_work(&floppy_work);
}
@@ -1008,7 +1008,7 @@ static void cancel_activity(void)
spin_lock_irqsave(&floppy_lock, flags);
do_floppy = NULL;
- PREPARE_WORK(&floppy_work, (void *)empty, NULL);
+ PREPARE_WORK(&floppy_work, (work_func_t)empty);
del_timer(&fd_timer);
spin_unlock_irqrestore(&floppy_lock, flags);
}
@@ -1726,7 +1726,7 @@ static void print_result(char *message, int inr)
}
/* interrupt handler. Note that this can be called externally on the Sparc */
-irqreturn_t floppy_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+irqreturn_t floppy_interrupt(int irq, void *dev_id)
{
void (*handler) (void) = do_floppy;
int do_print;
@@ -1868,7 +1868,7 @@ static void show_floppy(void)
printk("fdc_busy=%lu\n", fdc_busy);
if (do_floppy)
printk("do_floppy=%p\n", do_floppy);
- if (floppy_work.pending)
+ if (work_pending(&floppy_work))
printk("floppy_work.func=%p\n", floppy_work.func);
if (timer_pending(&fd_timer))
printk("fd_timer.function=%p\n", fd_timer.function);
@@ -2991,8 +2991,8 @@ static void do_fd_request(request_queue_t * q)
if (usage_count == 0) {
printk("warning: usage count=0, current_req=%p exiting\n",
current_req);
- printk("sect=%ld flags=%lx\n", (long)current_req->sector,
- current_req->flags);
+ printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector,
+ current_req->cmd_type, current_req->cmd_flags);
return;
}
if (test_bit(0, &fdc_busy)) {
@@ -4498,7 +4498,7 @@ static void floppy_release_irq_and_dma(void)
printk("floppy timer still active:%s\n", timeout_message);
if (timer_pending(&fd_timer))
printk("auxiliary floppy timer still active\n");
- if (floppy_work.pending)
+ if (work_pending(&floppy_work))
printk("work still pending\n");
#endif
old_fdc = fdc;
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 7b3b94ddddc..6b5b6420740 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -66,12 +66,14 @@
#include <linux/swap.h>
#include <linux/slab.h>
#include <linux/loop.h>
+#include <linux/compat.h>
#include <linux/suspend.h>
#include <linux/writeback.h>
#include <linux/buffer_head.h> /* for invalidate_bdev() */
#include <linux/completion.h>
#include <linux/highmem.h>
#include <linux/gfp.h>
+#include <linux/kthread.h>
#include <asm/uaccess.h>
@@ -293,7 +295,7 @@ fail:
* and do_lo_send_write().
*/
static int __do_lo_send_write(struct file *file,
- u8 __user *buf, const int len, loff_t pos)
+ u8 *buf, const int len, loff_t pos)
{
ssize_t bw;
mm_segment_t old_fs = get_fs();
@@ -322,7 +324,7 @@ static int do_lo_send_direct_write(struct loop_device *lo,
struct bio_vec *bvec, int bsize, loff_t pos, struct page *page)
{
ssize_t bw = __do_lo_send_write(lo->lo_backing_file,
- (u8 __user *)kmap(bvec->bv_page) + bvec->bv_offset,
+ kmap(bvec->bv_page) + bvec->bv_offset,
bvec->bv_len, pos);
kunmap(bvec->bv_page);
cond_resched();
@@ -349,7 +351,7 @@ static int do_lo_send_write(struct loop_device *lo, struct bio_vec *bvec,
bvec->bv_offset, bvec->bv_len, pos >> 9);
if (likely(!ret))
return __do_lo_send_write(lo->lo_backing_file,
- (u8 __user *)page_address(page), bvec->bv_len,
+ page_address(page), bvec->bv_len,
pos);
printk(KERN_ERR "loop: Transfer error at byte offset %llu, "
"length %i.\n", (unsigned long long)pos, bvec->bv_len);
@@ -522,15 +524,12 @@ static int loop_make_request(request_queue_t *q, struct bio *old_bio)
goto out;
if (unlikely(rw == WRITE && (lo->lo_flags & LO_FLAGS_READ_ONLY)))
goto out;
- lo->lo_pending++;
loop_add_bio(lo, old_bio);
+ wake_up(&lo->lo_event);
spin_unlock_irq(&lo->lo_lock);
- complete(&lo->lo_bh_done);
return 0;
out:
- if (lo->lo_pending == 0)
- complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
bio_io_error(old_bio, old_bio->bi_size);
return 0;
@@ -570,14 +569,18 @@ static inline void loop_handle_bio(struct loop_device *lo, struct bio *bio)
* to avoid blocking in our make_request_fn. it also does loop decrypting
* on reads for block backed loop, as that is too heavy to do from
* b_end_io context where irqs may be disabled.
+ *
+ * Loop explanation: loop_clr_fd() sets lo_state to Lo_rundown before
+ * calling kthread_stop(). Therefore once kthread_should_stop() is
+ * true, make_request will not place any more requests. Therefore
+ * once kthread_should_stop() is true and lo_bio is NULL, we are
+ * done with the loop.
*/
static int loop_thread(void *data)
{
struct loop_device *lo = data;
struct bio *bio;
- daemonize("loop%d", lo->lo_number);
-
/*
* loop can be used in an encrypted device,
* hence, it mustn't be stopped at all
@@ -587,47 +590,21 @@ static int loop_thread(void *data)
set_user_nice(current, -20);
- lo->lo_state = Lo_bound;
- lo->lo_pending = 1;
+ while (!kthread_should_stop() || lo->lo_bio) {
- /*
- * complete it, we are running
- */
- complete(&lo->lo_done);
-
- for (;;) {
- int pending;
+ wait_event_interruptible(lo->lo_event,
+ lo->lo_bio || kthread_should_stop());
- if (wait_for_completion_interruptible(&lo->lo_bh_done))
+ if (!lo->lo_bio)
continue;
-
spin_lock_irq(&lo->lo_lock);
-
- /*
- * could be completed because of tear-down, not pending work
- */
- if (unlikely(!lo->lo_pending)) {
- spin_unlock_irq(&lo->lo_lock);
- break;
- }
-
bio = loop_get_bio(lo);
- lo->lo_pending--;
- pending = lo->lo_pending;
spin_unlock_irq(&lo->lo_lock);
BUG_ON(!bio);
loop_handle_bio(lo, bio);
-
- /*
- * upped both for pending work and tear-down, lo_pending
- * will hit zero then
- */
- if (unlikely(!pending))
- break;
}
- complete(&lo->lo_done);
return 0;
}
@@ -662,7 +639,8 @@ static void do_loop_switch(struct loop_device *lo, struct switch_request *p)
mapping_set_gfp_mask(old_file->f_mapping, lo->old_gfp_mask);
lo->lo_backing_file = file;
- lo->lo_blocksize = mapping->host->i_blksize;
+ lo->lo_blocksize = S_ISBLK(mapping->host->i_mode) ?
+ mapping->host->i_bdev->bd_block_size : PAGE_SIZE;
lo->old_gfp_mask = mapping_gfp_mask(mapping);
mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS));
complete(&p->wait);
@@ -794,7 +772,9 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write)
lo_flags |= LO_FLAGS_READ_ONLY;
- lo_blocksize = inode->i_blksize;
+ lo_blocksize = S_ISBLK(inode->i_mode) ?
+ inode->i_bdev->bd_block_size : PAGE_SIZE;
+
error = 0;
} else {
goto out_putf;
@@ -837,12 +817,26 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
set_blocksize(bdev, lo_blocksize);
- error = kernel_thread(loop_thread, lo, CLONE_KERNEL);
- if (error < 0)
- goto out_putf;
- wait_for_completion(&lo->lo_done);
+ lo->lo_thread = kthread_create(loop_thread, lo, "loop%d",
+ lo->lo_number);
+ if (IS_ERR(lo->lo_thread)) {
+ error = PTR_ERR(lo->lo_thread);
+ goto out_clr;
+ }
+ lo->lo_state = Lo_bound;
+ wake_up_process(lo->lo_thread);
return 0;
+out_clr:
+ lo->lo_thread = NULL;
+ lo->lo_device = NULL;
+ lo->lo_backing_file = NULL;
+ lo->lo_flags = 0;
+ set_capacity(disks[lo->lo_number], 0);
+ invalidate_bdev(bdev, 0);
+ bd_set_size(bdev, 0);
+ mapping_set_gfp_mask(mapping, lo->old_gfp_mask);
+ lo->lo_state = Lo_unbound;
out_putf:
fput(file);
out:
@@ -904,12 +898,9 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
spin_lock_irq(&lo->lo_lock);
lo->lo_state = Lo_rundown;
- lo->lo_pending--;
- if (!lo->lo_pending)
- complete(&lo->lo_bh_done);
spin_unlock_irq(&lo->lo_lock);
- wait_for_completion(&lo->lo_done);
+ kthread_stop(lo->lo_thread);
lo->lo_backing_file = NULL;
@@ -922,6 +913,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
lo->lo_sizelimit = 0;
lo->lo_encrypt_key_size = 0;
lo->lo_flags = 0;
+ lo->lo_thread = NULL;
memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
memset(lo->lo_file_name, 0, LO_NAME_SIZE);
@@ -1008,7 +1000,7 @@ loop_get_status(struct loop_device *lo, struct loop_info64 *info)
if (lo->lo_state != Lo_bound)
return -ENXIO;
- error = vfs_getattr(file->f_vfsmnt, file->f_dentry, &stat);
+ error = vfs_getattr(file->f_path.mnt, file->f_path.dentry, &stat);
if (error)
return error;
memset(info, 0, sizeof(*info));
@@ -1174,6 +1166,162 @@ static int lo_ioctl(struct inode * inode, struct file * file,
return err;
}
+#ifdef CONFIG_COMPAT
+struct compat_loop_info {
+ compat_int_t lo_number; /* ioctl r/o */
+ compat_dev_t lo_device; /* ioctl r/o */
+ compat_ulong_t lo_inode; /* ioctl r/o */
+ compat_dev_t lo_rdevice; /* ioctl r/o */
+ compat_int_t lo_offset;
+ compat_int_t lo_encrypt_type;
+ compat_int_t lo_encrypt_key_size; /* ioctl w/o */
+ compat_int_t lo_flags; /* ioctl r/o */
+ char lo_name[LO_NAME_SIZE];
+ unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */
+ compat_ulong_t lo_init[2];
+ char reserved[4];
+};
+
+/*
+ * Transfer 32-bit compatibility structure in userspace to 64-bit loop info
+ * - noinlined to reduce stack space usage in main part of driver
+ */
+static noinline int
+loop_info64_from_compat(const struct compat_loop_info __user *arg,
+ struct loop_info64 *info64)
+{
+ struct compat_loop_info info;
+
+ if (copy_from_user(&info, arg, sizeof(info)))
+ return -EFAULT;
+
+ memset(info64, 0, sizeof(*info64));
+ info64->lo_number = info.lo_number;
+ info64->lo_device = info.lo_device;
+ info64->lo_inode = info.lo_inode;
+ info64->lo_rdevice = info.lo_rdevice;
+ info64->lo_offset = info.lo_offset;
+ info64->lo_sizelimit = 0;
+ info64->lo_encrypt_type = info.lo_encrypt_type;
+ info64->lo_encrypt_key_size = info.lo_encrypt_key_size;
+ info64->lo_flags = info.lo_flags;
+ info64->lo_init[0] = info.lo_init[0];
+ info64->lo_init[1] = info.lo_init[1];
+ if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+ memcpy(info64->lo_crypt_name, info.lo_name, LO_NAME_SIZE);
+ else
+ memcpy(info64->lo_file_name, info.lo_name, LO_NAME_SIZE);
+ memcpy(info64->lo_encrypt_key, info.lo_encrypt_key, LO_KEY_SIZE);
+ return 0;
+}
+
+/*
+ * Transfer 64-bit loop info to 32-bit compatibility structure in userspace
+ * - noinlined to reduce stack space usage in main part of driver
+ */
+static noinline int
+loop_info64_to_compat(const struct loop_info64 *info64,
+ struct compat_loop_info __user *arg)
+{
+ struct compat_loop_info info;
+
+ memset(&info, 0, sizeof(info));
+ info.lo_number = info64->lo_number;
+ info.lo_device = info64->lo_device;
+ info.lo_inode = info64->lo_inode;
+ info.lo_rdevice = info64->lo_rdevice;
+ info.lo_offset = info64->lo_offset;
+ info.lo_encrypt_type = info64->lo_encrypt_type;
+ info.lo_encrypt_key_size = info64->lo_encrypt_key_size;
+ info.lo_flags = info64->lo_flags;
+ info.lo_init[0] = info64->lo_init[0];
+ info.lo_init[1] = info64->lo_init[1];
+ if (info.lo_encrypt_type == LO_CRYPT_CRYPTOAPI)
+ memcpy(info.lo_name, info64->lo_crypt_name, LO_NAME_SIZE);
+ else
+ memcpy(info.lo_name, info64->lo_file_name, LO_NAME_SIZE);
+ memcpy(info.lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE);
+
+ /* error in case values were truncated */
+ if (info.lo_device != info64->lo_device ||
+ info.lo_rdevice != info64->lo_rdevice ||
+ info.lo_inode != info64->lo_inode ||
+ info.lo_offset != info64->lo_offset ||
+ info.lo_init[0] != info64->lo_init[0] ||
+ info.lo_init[1] != info64->lo_init[1])
+ return -EOVERFLOW;
+
+ if (copy_to_user(arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+}
+
+static int
+loop_set_status_compat(struct loop_device *lo,
+ const struct compat_loop_info __user *arg)
+{
+ struct loop_info64 info64;
+ int ret;
+
+ ret = loop_info64_from_compat(arg, &info64);
+ if (ret < 0)
+ return ret;
+ return loop_set_status(lo, &info64);
+}
+
+static int
+loop_get_status_compat(struct loop_device *lo,
+ struct compat_loop_info __user *arg)
+{
+ struct loop_info64 info64;
+ int err = 0;
+
+ if (!arg)
+ err = -EINVAL;
+ if (!err)
+ err = loop_get_status(lo, &info64);
+ if (!err)
+ err = loop_info64_to_compat(&info64, arg);
+ return err;
+}
+
+static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ struct inode *inode = file->f_path.dentry->d_inode;
+ struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
+ int err;
+
+ lock_kernel();
+ switch(cmd) {
+ case LOOP_SET_STATUS:
+ mutex_lock(&lo->lo_ctl_mutex);
+ err = loop_set_status_compat(
+ lo, (const struct compat_loop_info __user *) arg);
+ mutex_unlock(&lo->lo_ctl_mutex);
+ break;
+ case LOOP_GET_STATUS:
+ mutex_lock(&lo->lo_ctl_mutex);
+ err = loop_get_status_compat(
+ lo, (struct compat_loop_info __user *) arg);
+ mutex_unlock(&lo->lo_ctl_mutex);
+ break;
+ case LOOP_CLR_FD:
+ case LOOP_GET_STATUS64:
+ case LOOP_SET_STATUS64:
+ arg = (unsigned long) compat_ptr(arg);
+ case LOOP_SET_FD:
+ case LOOP_CHANGE_FD:
+ err = lo_ioctl(inode, file, cmd, arg);
+ break;
+ default:
+ err = -ENOIOCTLCMD;
+ break;
+ }
+ unlock_kernel();
+ return err;
+}
+#endif
+
static int lo_open(struct inode *inode, struct file *file)
{
struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
@@ -1201,6 +1349,9 @@ static struct block_device_operations lo_fops = {
.open = lo_open,
.release = lo_release,
.ioctl = lo_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = lo_compat_ioctl,
+#endif
};
/*
@@ -1284,9 +1435,9 @@ static int __init loop_init(void)
if (!lo->lo_queue)
goto out_mem4;
mutex_init(&lo->lo_ctl_mutex);
- init_completion(&lo->lo_done);
- init_completion(&lo->lo_bh_done);
lo->lo_number = i;
+ lo->lo_thread = NULL;
+ init_waitqueue_head(&lo->lo_event);
spin_lock_init(&lo->lo_lock);
disk->major = LOOP_MAJOR;
disk->first_minor = i;
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index bdbade9a5cf..090796bef78 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -355,14 +355,30 @@ harderror:
return NULL;
}
+static ssize_t pid_show(struct gendisk *disk, char *page)
+{
+ return sprintf(page, "%ld\n",
+ (long) ((struct nbd_device *)disk->private_data)->pid);
+}
+
+static struct disk_attribute pid_attr = {
+ .attr = { .name = "pid", .mode = S_IRUGO },
+ .show = pid_show,
+};
+
static void nbd_do_it(struct nbd_device *lo)
{
struct request *req;
BUG_ON(lo->magic != LO_MAGIC);
+ lo->pid = current->pid;
+ sysfs_create_file(&lo->disk->kobj, &pid_attr.attr);
+
while ((req = nbd_read_stat(lo)) != NULL)
nbd_end_request(req);
+
+ sysfs_remove_file(&lo->disk->kobj, &pid_attr.attr);
return;
}
@@ -407,10 +423,10 @@ static void do_nbd_request(request_queue_t * q)
struct nbd_device *lo;
blkdev_dequeue_request(req);
- dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%lx)\n",
- req->rq_disk->disk_name, req, req->flags);
+ dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n",
+ req->rq_disk->disk_name, req, req->cmd_type);
- if (!(req->flags & REQ_CMD))
+ if (!blk_fs_request(req))
goto error_out;
lo = req->rq_disk->private_data;
@@ -489,7 +505,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
switch (cmd) {
case NBD_DISCONNECT:
printk(KERN_INFO "%s: NBD_DISCONNECT\n", lo->disk->disk_name);
- sreq.flags = REQ_SPECIAL;
+ sreq.cmd_type = REQ_TYPE_SPECIAL;
nbd_cmd(&sreq) = NBD_CMD_DISC;
/*
* Set these to sane values in case server implementation
@@ -521,7 +537,7 @@ static int nbd_ioctl(struct inode *inode, struct file *file,
error = -EINVAL;
file = fget(arg);
if (file) {
- inode = file->f_dentry->d_inode;
+ inode = file->f_path.dentry->d_inode;
if (S_ISSOCK(inode->i_mode)) {
lo->file = file;
lo->sock = SOCKET_I(inode);
diff --git a/drivers/block/paride/aten.c b/drivers/block/paride/aten.c
index c4d696d43dc..2695465568a 100644
--- a/drivers/block/paride/aten.c
+++ b/drivers/block/paride/aten.c
@@ -149,12 +149,12 @@ static struct pi_protocol aten = {
static int __init aten_init(void)
{
- return pi_register(&aten)-1;
+ return paride_register(&aten);
}
static void __exit aten_exit(void)
{
- pi_unregister( &aten );
+ paride_unregister( &aten );
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/bpck.c b/drivers/block/paride/bpck.c
index d462ff6b139..4f27e7392e3 100644
--- a/drivers/block/paride/bpck.c
+++ b/drivers/block/paride/bpck.c
@@ -464,12 +464,12 @@ static struct pi_protocol bpck = {
static int __init bpck_init(void)
{
- return pi_register(&bpck)-1;
+ return paride_register(&bpck);
}
static void __exit bpck_exit(void)
{
- pi_unregister(&bpck);
+ paride_unregister(&bpck);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/bpck6.c b/drivers/block/paride/bpck6.c
index 41a237c5957..ad124525ac2 100644
--- a/drivers/block/paride/bpck6.c
+++ b/drivers/block/paride/bpck6.c
@@ -31,10 +31,7 @@ static int verbose; /* set this to 1 to see debugging messages and whatnot */
#include <linux/slab.h>
#include <linux/types.h>
#include <asm/io.h>
-
-#if defined(CONFIG_PARPORT_MODULE)||defined(CONFIG_PARPORT)
#include <linux/parport.h>
-#endif
#include "ppc6lnx.c"
#include "paride.h"
@@ -139,11 +136,6 @@ static int bpck6_test_port ( PIA *pi ) /* check for 8-bit port */
PPCSTRUCT(pi)->ppc_id=pi->unit;
PPCSTRUCT(pi)->lpt_addr=pi->port;
-#ifdef CONFIG_PARPORT_PC_MODULE
-#define CONFIG_PARPORT_PC
-#endif
-
-#ifdef CONFIG_PARPORT_PC
/* look at the parport device to see if what modes we can use */
if(((struct pardevice *)(pi->pardev))->port->modes &
(PARPORT_MODE_EPP)
@@ -161,11 +153,6 @@ static int bpck6_test_port ( PIA *pi ) /* check for 8-bit port */
{
return 1;
}
-#else
- /* there is no way of knowing what kind of port we have
- default to the highest mode possible */
- return 5;
-#endif
}
static int bpck6_probe_unit ( PIA *pi )
@@ -265,12 +252,12 @@ static int __init bpck6_init(void)
printk(KERN_INFO "bpck6: Copyright 2001 by Micro Solutions, Inc., DeKalb IL. USA\n");
if(verbose)
printk(KERN_DEBUG "bpck6: verbose debug enabled.\n");
- return pi_register(&bpck6) - 1;
+ return paride_register(&bpck6);
}
static void __exit bpck6_exit(void)
{
- pi_unregister(&bpck6);
+ paride_unregister(&bpck6);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/comm.c b/drivers/block/paride/comm.c
index 43d61359d8e..9bcd3549532 100644
--- a/drivers/block/paride/comm.c
+++ b/drivers/block/paride/comm.c
@@ -205,12 +205,12 @@ static struct pi_protocol comm = {
static int __init comm_init(void)
{
- return pi_register(&comm)-1;
+ return paride_register(&comm);
}
static void __exit comm_exit(void)
{
- pi_unregister(&comm);
+ paride_unregister(&comm);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/dstr.c b/drivers/block/paride/dstr.c
index 04d53bf58e8..accc5c777cb 100644
--- a/drivers/block/paride/dstr.c
+++ b/drivers/block/paride/dstr.c
@@ -220,12 +220,12 @@ static struct pi_protocol dstr = {
static int __init dstr_init(void)
{
- return pi_register(&dstr)-1;
+ return paride_register(&dstr);
}
static void __exit dstr_exit(void)
{
- pi_unregister(&dstr);
+ paride_unregister(&dstr);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/epat.c b/drivers/block/paride/epat.c
index 55d1c0a1fb9..1bcdff77322 100644
--- a/drivers/block/paride/epat.c
+++ b/drivers/block/paride/epat.c
@@ -327,12 +327,12 @@ static int __init epat_init(void)
#ifdef CONFIG_PARIDE_EPATC8
epatc8 = 1;
#endif
- return pi_register(&epat)-1;
+ return paride_register(&epat);
}
static void __exit epat_exit(void)
{
- pi_unregister(&epat);
+ paride_unregister(&epat);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/epia.c b/drivers/block/paride/epia.c
index 0f2e0c292d8..fb0e782d055 100644
--- a/drivers/block/paride/epia.c
+++ b/drivers/block/paride/epia.c
@@ -303,12 +303,12 @@ static struct pi_protocol epia = {
static int __init epia_init(void)
{
- return pi_register(&epia)-1;
+ return paride_register(&epia);
}
static void __exit epia_exit(void)
{
- pi_unregister(&epia);
+ paride_unregister(&epia);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/fit2.c b/drivers/block/paride/fit2.c
index e0f0691d8bc..381283753ae 100644
--- a/drivers/block/paride/fit2.c
+++ b/drivers/block/paride/fit2.c
@@ -138,12 +138,12 @@ static struct pi_protocol fit2 = {
static int __init fit2_init(void)
{
- return pi_register(&fit2)-1;
+ return paride_register(&fit2);
}
static void __exit fit2_exit(void)
{
- pi_unregister(&fit2);
+ paride_unregister(&fit2);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/fit3.c b/drivers/block/paride/fit3.c
index 15400e7bc66..275d269458e 100644
--- a/drivers/block/paride/fit3.c
+++ b/drivers/block/paride/fit3.c
@@ -198,12 +198,12 @@ static struct pi_protocol fit3 = {
static int __init fit3_init(void)
{
- return pi_register(&fit3)-1;
+ return paride_register(&fit3);
}
static void __exit fit3_exit(void)
{
- pi_unregister(&fit3);
+ paride_unregister(&fit3);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/friq.c b/drivers/block/paride/friq.c
index 5ea2904d281..4f2ba244689 100644
--- a/drivers/block/paride/friq.c
+++ b/drivers/block/paride/friq.c
@@ -263,12 +263,12 @@ static struct pi_protocol friq = {
static int __init friq_init(void)
{
- return pi_register(&friq)-1;
+ return paride_register(&friq);
}
static void __exit friq_exit(void)
{
- pi_unregister(&friq);
+ paride_unregister(&friq);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/frpw.c b/drivers/block/paride/frpw.c
index 56b3824b153..c3cde364603 100644
--- a/drivers/block/paride/frpw.c
+++ b/drivers/block/paride/frpw.c
@@ -300,12 +300,12 @@ static struct pi_protocol frpw = {
static int __init frpw_init(void)
{
- return pi_register(&frpw)-1;
+ return paride_register(&frpw);
}
static void __exit frpw_exit(void)
{
- pi_unregister(&frpw);
+ paride_unregister(&frpw);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/jumbo b/drivers/block/paride/jumbo
deleted file mode 100644
index e793b9cb7e7..00000000000
--- a/drivers/block/paride/jumbo
+++ /dev/null
@@ -1,70 +0,0 @@
-#!/bin/sh
-#
-# This script can be used to build "jumbo" modules that contain the
-# base PARIDE support, one protocol module and one high-level driver.
-#
-echo -n "High level driver [pcd] : "
-read X
-HLD=${X:-pcd}
-#
-echo -n "Protocol module [bpck] : "
-read X
-PROTO=${X:-bpck}
-#
-echo -n "Use MODVERSIONS [y] ? "
-read X
-UMODV=${X:-y}
-#
-echo -n "For SMP kernel [n] ? "
-read X
-USMP=${X:-n}
-#
-echo -n "Support PARPORT [n] ? "
-read X
-UPARP=${X:-n}
-#
-echo
-#
-case $USMP in
- y* | Y* ) FSMP="-DCONFIG_SMP"
- ;;
- *) FSMP=""
- ;;
-esac
-#
-MODI="-include ../../../include/linux/modversions.h"
-#
-case $UMODV in
- y* | Y* ) FMODV="-DMODVERSIONS $MODI"
- ;;
- *) FMODV=""
- ;;
-esac
-#
-case $UPARP in
- y* | Y* ) FPARP="-DCONFIG_PARPORT"
- ;;
- *) FPARP=""
- ;;
-esac
-#
-TARG=$HLD-$PROTO.o
-FPROTO=-DCONFIG_PARIDE_`echo "$PROTO" | tr [a-z] [A-Z]`
-FK="-D__KERNEL__ -I ../../../include"
-FLCH=-D_LINUX_CONFIG_H
-#
-echo cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
-cc $FK $FSMP $FLCH $FPARP $FPROTO $FMODV -Wall -O2 -o Jb.o -c paride.c
-#
-echo cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
-cc $FK $FSMP $FMODV -Wall -O2 -o Jp.o -c $PROTO.c
-#
-echo cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
-cc $FK $FSMP $FMODV -DMODULE -DPARIDE_JUMBO -Wall -O2 -o Jd.o -c $HLD.c
-#
-echo ld -r -o $TARG Jp.o Jb.o Jd.o
-ld -r -o $TARG Jp.o Jb.o Jd.o
-#
-#
-rm Jp.o Jb.o Jd.o
-#
diff --git a/drivers/block/paride/kbic.c b/drivers/block/paride/kbic.c
index d983bcea76f..35999c415ee 100644
--- a/drivers/block/paride/kbic.c
+++ b/drivers/block/paride/kbic.c
@@ -283,13 +283,21 @@ static struct pi_protocol k971 = {
static int __init kbic_init(void)
{
- return (pi_register(&k951)||pi_register(&k971))-1;
+ int rv;
+
+ rv = paride_register(&k951);
+ if (rv < 0)
+ return rv;
+ rv = paride_register(&k971);
+ if (rv < 0)
+ paride_unregister(&k951);
+ return rv;
}
static void __exit kbic_exit(void)
{
- pi_unregister(&k951);
- pi_unregister(&k971);
+ paride_unregister(&k951);
+ paride_unregister(&k971);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/ktti.c b/drivers/block/paride/ktti.c
index 6c7edbfba9a..117ab0e8ccf 100644
--- a/drivers/block/paride/ktti.c
+++ b/drivers/block/paride/ktti.c
@@ -115,12 +115,12 @@ static struct pi_protocol ktti = {
static int __init ktti_init(void)
{
- return pi_register(&ktti)-1;
+ return paride_register(&ktti);
}
static void __exit ktti_exit(void)
{
- pi_unregister(&ktti);
+ paride_unregister(&ktti);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/on20.c b/drivers/block/paride/on20.c
index 9f8e0109680..0173697a1a4 100644
--- a/drivers/block/paride/on20.c
+++ b/drivers/block/paride/on20.c
@@ -140,12 +140,12 @@ static struct pi_protocol on20 = {
static int __init on20_init(void)
{
- return pi_register(&on20)-1;
+ return paride_register(&on20);
}
static void __exit on20_exit(void)
{
- pi_unregister(&on20);
+ paride_unregister(&on20);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/on26.c b/drivers/block/paride/on26.c
index 0f833caa210..95ba256921f 100644
--- a/drivers/block/paride/on26.c
+++ b/drivers/block/paride/on26.c
@@ -306,12 +306,12 @@ static struct pi_protocol on26 = {
static int __init on26_init(void)
{
- return pi_register(&on26)-1;
+ return paride_register(&on26);
}
static void __exit on26_exit(void)
{
- pi_unregister(&on26);
+ paride_unregister(&on26);
}
MODULE_LICENSE("GPL");
diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c
index 4b258f7836f..48c50f11f63 100644
--- a/drivers/block/paride/paride.c
+++ b/drivers/block/paride/paride.c
@@ -29,14 +29,7 @@
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <linux/sched.h> /* TASK_* */
-
-#ifdef CONFIG_PARPORT_MODULE
-#define CONFIG_PARPORT
-#endif
-
-#ifdef CONFIG_PARPORT
#include <linux/parport.h>
-#endif
#include "paride.h"
@@ -76,8 +69,6 @@ void pi_read_block(PIA * pi, char *buf, int count)
EXPORT_SYMBOL(pi_read_block);
-#ifdef CONFIG_PARPORT
-
static void pi_wake_up(void *p)
{
PIA *pi = (PIA *) p;
@@ -100,11 +91,8 @@ static void pi_wake_up(void *p)
cont();
}
-#endif
-
int pi_schedule_claimed(PIA * pi, void (*cont) (void))
{
-#ifdef CONFIG_PARPORT
unsigned long flags;
spin_lock_irqsave(&pi_spinlock, flags);
@@ -115,7 +103,6 @@ int pi_schedule_claimed(PIA * pi, void (*cont) (void))
}
pi->claimed = 1;
spin_unlock_irqrestore(&pi_spinlock, flags);
-#endif
return 1;
}
EXPORT_SYMBOL(pi_schedule_claimed);
@@ -133,20 +120,16 @@ static void pi_claim(PIA * pi)
if (pi->claimed)
return;
pi->claimed = 1;
-#ifdef CONFIG_PARPORT
if (pi->pardev)
wait_event(pi->parq,
!parport_claim((struct pardevice *) pi->pardev));
-#endif
}
static void pi_unclaim(PIA * pi)
{
pi->claimed = 0;
-#ifdef CONFIG_PARPORT
if (pi->pardev)
parport_release((struct pardevice *) (pi->pardev));
-#endif
}
void pi_connect(PIA * pi)
@@ -167,21 +150,15 @@ EXPORT_SYMBOL(pi_disconnect);
static void pi_unregister_parport(PIA * pi)
{
-#ifdef CONFIG_PARPORT
if (pi->pardev) {
parport_unregister_device((struct pardevice *) (pi->pardev));
pi->pardev = NULL;
}
-#endif
}
void pi_release(PIA * pi)
{
pi_unregister_parport(pi);
-#ifndef CONFIG_PARPORT
- if (pi->reserved)
- release_region(pi->port, pi->reserved);
-#endif /* !CONFIG_PARPORT */
if (pi->proto->release_proto)
pi->proto->release_proto(pi);
module_put(pi->proto->owner);
@@ -229,7 +206,7 @@ static int pi_test_proto(PIA * pi, char *scratch, int verbose)
return res;
}
-int pi_register(PIP * pr)
+int paride_register(PIP * pr)
{
int k;
@@ -237,24 +214,24 @@ int pi_register(PIP * pr)
if (protocols[k] && !strcmp(pr->name, protocols[k]->name)) {
printk("paride: %s protocol already registered\n",
pr->name);
- return 0;
+ return -1;
}
k = 0;
while ((k < MAX_PROTOS) && (protocols[k]))
k++;
if (k == MAX_PROTOS) {
printk("paride: protocol table full\n");
- return 0;
+ return -1;
}
protocols[k] = pr;
pr->index = k;
printk("paride: %s registered as protocol %d\n", pr->name, k);
- return 1;
+ return 0;
}
-EXPORT_SYMBOL(pi_register);
+EXPORT_SYMBOL(paride_register);
-void pi_unregister(PIP * pr)
+void paride_unregister(PIP * pr)
{
if (!pr)
return;
@@ -265,12 +242,10 @@ void pi_unregister(PIP * pr)
protocols[pr->index] = NULL;
}
-EXPORT_SYMBOL(pi_unregister);
+EXPORT_SYMBOL(paride_unregister);
static int pi_register_parport(PIA * pi, int verbose)
{
-#ifdef CONFIG_PARPORT
-
struct parport *port;
port = parport_find_base(pi->port);
@@ -290,7 +265,6 @@ static int pi_register_parport(PIA * pi, int verbose)
printk("%s: 0x%x is %s\n", pi->device, pi->port, port->name);
pi->parname = (char *) port->name;
-#endif
return 1;
}
@@ -447,13 +421,6 @@ int pi_init(PIA * pi, int autoprobe, int port, int mode,
printk("%s: Adapter not found\n", device);
return 0;
}
-#ifndef CONFIG_PARPORT
- if (!request_region(pi->port, pi->reserved, pi->device)) {
- printk(KERN_WARNING "paride: Unable to request region 0x%x\n",
- pi->port);
- return 0;
- }
-#endif /* !CONFIG_PARPORT */
if (pi->parname)
printk("%s: Sharing %s at 0x%x\n", pi->device,
diff --git a/drivers/block/paride/paride.h b/drivers/block/paride/paride.h
index c6d98ef09e4..2bddbf45518 100644
--- a/drivers/block/paride/paride.h
+++ b/drivers/block/paride/paride.h
@@ -163,8 +163,8 @@ struct pi_protocol {
typedef struct pi_protocol PIP;
-extern int pi_register( PIP * );
-extern void pi_unregister ( PIP * );
+extern int paride_register( PIP * );
+extern void paride_unregister ( PIP * );
#endif /* __DRIVERS_PARIDE_H__ */
/* end of paride.h */
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
index ac5ba462710..c852eed91e4 100644
--- a/drivers/block/paride/pcd.c
+++ b/drivers/block/paride/pcd.c
@@ -912,12 +912,12 @@ static int __init pcd_init(void)
int unit;
if (disable)
- return -1;
+ return -EINVAL;
pcd_init_units();
if (pcd_detect())
- return -1;
+ return -ENODEV;
/* get the atapi capabilities page */
pcd_probe_capabilities();
@@ -925,7 +925,7 @@ static int __init pcd_init(void)
if (register_blkdev(major, name)) {
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
put_disk(cd->disk);
- return -1;
+ return -EBUSY;
}
pcd_queue = blk_init_queue(do_pcd_request, &pcd_lock);
@@ -933,7 +933,7 @@ static int __init pcd_init(void)
unregister_blkdev(major, name);
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++)
put_disk(cd->disk);
- return -1;
+ return -ENOMEM;
}
for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) {
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c
index 2403721f9db..9d9bff23f42 100644
--- a/drivers/block/paride/pd.c
+++ b/drivers/block/paride/pd.c
@@ -352,19 +352,19 @@ static enum action (*phase)(void);
static void run_fsm(void);
-static void ps_tq_int( void *data);
+static void ps_tq_int(struct work_struct *work);
-static DECLARE_WORK(fsm_tq, ps_tq_int, NULL);
+static DECLARE_DELAYED_WORK(fsm_tq, ps_tq_int);
static void schedule_fsm(void)
{
if (!nice)
- schedule_work(&fsm_tq);
+ schedule_delayed_work(&fsm_tq, 0);
else
schedule_delayed_work(&fsm_tq, nice-1);
}
-static void ps_tq_int(void *data)
+static void ps_tq_int(struct work_struct *work)
{
run_fsm();
}
@@ -437,7 +437,7 @@ static char *pd_buf; /* buffer for request in progress */
static enum action do_pd_io_start(void)
{
- if (pd_req->flags & REQ_SPECIAL) {
+ if (blk_special_request(pd_req)) {
phase = pd_special;
return pd_special();
}
@@ -713,20 +713,18 @@ static void do_pd_request(request_queue_t * q)
static int pd_special_command(struct pd_unit *disk,
enum action (*func)(struct pd_unit *disk))
{
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
struct request rq;
int err = 0;
memset(&rq, 0, sizeof(rq));
rq.errors = 0;
- rq.rq_status = RQ_ACTIVE;
rq.rq_disk = disk->gd;
rq.ref_count = 1;
- rq.waiting = &wait;
+ rq.end_io_data = &wait;
rq.end_io = blk_end_sync_rq;
blk_insert_request(disk->gd->queue, &rq, 0, func);
wait_for_completion(&wait);
- rq.waiting = NULL;
if (rq.errors)
err = -EIO;
blk_put_request(&rq);
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c
index 1a9dee19efc..7cdaa195126 100644
--- a/drivers/block/paride/pf.c
+++ b/drivers/block/paride/pf.c
@@ -933,25 +933,25 @@ static int __init pf_init(void)
int unit;
if (disable)
- return -1;
+ return -EINVAL;
pf_init_units();
if (pf_detect())
- return -1;
+ return -ENODEV;
pf_busy = 0;
if (register_blkdev(major, name)) {
for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
put_disk(pf->disk);
- return -1;
+ return -EBUSY;
}
pf_queue = blk_init_queue(do_pf_request, &pf_spin_lock);
if (!pf_queue) {
unregister_blkdev(major, name);
for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++)
put_disk(pf->disk);
- return -1;
+ return -ENOMEM;
}
blk_queue_max_phys_segments(pf_queue, cluster);
diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c
index 13f998aa1cd..9970aedbb5d 100644
--- a/drivers/block/paride/pg.c
+++ b/drivers/block/paride/pg.c
@@ -646,14 +646,14 @@ static int __init pg_init(void)
int err;
if (disable){
- err = -1;
+ err = -EINVAL;
goto out;
}
pg_init_units();
if (pg_detect()) {
- err = -1;
+ err = -ENODEV;
goto out;
}
diff --git a/drivers/block/paride/pseudo.h b/drivers/block/paride/pseudo.h
index 932342d7a8e..bc370329414 100644
--- a/drivers/block/paride/pseudo.h
+++ b/drivers/block/paride/pseudo.h
@@ -35,7 +35,7 @@
#include <linux/sched.h>
#include <linux/workqueue.h>
-static void ps_tq_int( void *data);
+static void ps_tq_int(struct work_struct *work);
static void (* ps_continuation)(void);
static int (* ps_ready)(void);
@@ -45,7 +45,7 @@ static int ps_nice = 0;
static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused)));
-static DECLARE_WORK(ps_tq, ps_tq_int, NULL);
+static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int);
static void ps_set_intr(void (*continuation)(void),
int (*ready)(void),
@@ -63,14 +63,14 @@ static void ps_set_intr(void (*continuation)(void),
if (!ps_tq_active) {
ps_tq_active = 1;
if (!ps_nice)
- schedule_work(&ps_tq);
+ schedule_delayed_work(&ps_tq, 0);
else
schedule_delayed_work(&ps_tq, ps_nice-1);
}
spin_unlock_irqrestore(&ps_spinlock,flags);
}
-static void ps_tq_int(void *data)
+static void ps_tq_int(struct work_struct *work)
{
void (*con)(void);
unsigned long flags;
@@ -92,7 +92,7 @@ static void ps_tq_int(void *data)
}
ps_tq_active = 1;
if (!ps_nice)
- schedule_work(&ps_tq);
+ schedule_delayed_work(&ps_tq, 0);
else
schedule_delayed_work(&ps_tq, ps_nice-1);
spin_unlock_irqrestore(&ps_spinlock,flags);
diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c
index 35fb2663672..c902b25e486 100644
--- a/drivers/block/paride/pt.c
+++ b/drivers/block/paride/pt.c
@@ -946,12 +946,12 @@ static int __init pt_init(void)
int err;
if (disable) {
- err = -1;
+ err = -EINVAL;
goto out;
}
if (pt_detect()) {
- err = -1;
+ err = -ENODEV;
goto out;
}
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 451b996bba9..7c95c762950 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2000 Jens Axboe <axboe@suse.de>
* Copyright (C) 2001-2004 Peter Osterlund <petero2@telia.com>
+ * Copyright (C) 2006 Thomas Maier <balagi@justmail.de>
*
* May be copied or modified under the terms of the GNU General Public
* License. See linux/COPYING for more information.
@@ -54,14 +55,18 @@
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/miscdevice.h>
-#include <linux/suspend.h>
+#include <linux/freezer.h>
#include <linux/mutex.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_ioctl.h>
#include <scsi/scsi.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
#include <asm/uaccess.h>
+#define DRIVER_NAME "pktcdvd"
+
#if PACKET_DEBUG
#define DPRINTK(fmt, args...) printk(KERN_NOTICE fmt, ##args)
#else
@@ -80,16 +85,431 @@
static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
static struct proc_dir_entry *pkt_proc;
-static int pkt_major;
+static int pktdev_major;
+static int write_congestion_on = PKT_WRITE_CONGESTION_ON;
+static int write_congestion_off = PKT_WRITE_CONGESTION_OFF;
static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */
static mempool_t *psd_pool;
+static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */
+static struct dentry *pkt_debugfs_root = NULL; /* /debug/pktcdvd */
+
+/* forward declaration */
+static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev);
+static int pkt_remove_dev(dev_t pkt_dev);
+static int pkt_seq_show(struct seq_file *m, void *p);
+
+
+
+/*
+ * create and register a pktcdvd kernel object.
+ */
+static struct pktcdvd_kobj* pkt_kobj_create(struct pktcdvd_device *pd,
+ const char* name,
+ struct kobject* parent,
+ struct kobj_type* ktype)
+{
+ struct pktcdvd_kobj *p;
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return NULL;
+ kobject_set_name(&p->kobj, "%s", name);
+ p->kobj.parent = parent;
+ p->kobj.ktype = ktype;
+ p->pd = pd;
+ if (kobject_register(&p->kobj) != 0)
+ return NULL;
+ return p;
+}
+/*
+ * remove a pktcdvd kernel object.
+ */
+static void pkt_kobj_remove(struct pktcdvd_kobj *p)
+{
+ if (p)
+ kobject_unregister(&p->kobj);
+}
+/*
+ * default release function for pktcdvd kernel objects.
+ */
+static void pkt_kobj_release(struct kobject *kobj)
+{
+ kfree(to_pktcdvdkobj(kobj));
+}
+
+
+/**********************************************************
+ *
+ * sysfs interface for pktcdvd
+ * by (C) 2006 Thomas Maier <balagi@justmail.de>
+ *
+ **********************************************************/
+
+#define DEF_ATTR(_obj,_name,_mode) \
+ static struct attribute _obj = { \
+ .name = _name, .owner = THIS_MODULE, .mode = _mode }
+
+/**********************************************************
+ /sys/class/pktcdvd/pktcdvd[0-7]/
+ stat/reset
+ stat/packets_started
+ stat/packets_finished
+ stat/kb_written
+ stat/kb_read
+ stat/kb_read_gather
+ write_queue/size
+ write_queue/congestion_off
+ write_queue/congestion_on
+ **********************************************************/
+
+DEF_ATTR(kobj_pkt_attr_st1, "reset", 0200);
+DEF_ATTR(kobj_pkt_attr_st2, "packets_started", 0444);
+DEF_ATTR(kobj_pkt_attr_st3, "packets_finished", 0444);
+DEF_ATTR(kobj_pkt_attr_st4, "kb_written", 0444);
+DEF_ATTR(kobj_pkt_attr_st5, "kb_read", 0444);
+DEF_ATTR(kobj_pkt_attr_st6, "kb_read_gather", 0444);
+
+static struct attribute *kobj_pkt_attrs_stat[] = {
+ &kobj_pkt_attr_st1,
+ &kobj_pkt_attr_st2,
+ &kobj_pkt_attr_st3,
+ &kobj_pkt_attr_st4,
+ &kobj_pkt_attr_st5,
+ &kobj_pkt_attr_st6,
+ NULL
+};
+
+DEF_ATTR(kobj_pkt_attr_wq1, "size", 0444);
+DEF_ATTR(kobj_pkt_attr_wq2, "congestion_off", 0644);
+DEF_ATTR(kobj_pkt_attr_wq3, "congestion_on", 0644);
+
+static struct attribute *kobj_pkt_attrs_wqueue[] = {
+ &kobj_pkt_attr_wq1,
+ &kobj_pkt_attr_wq2,
+ &kobj_pkt_attr_wq3,
+ NULL
+};
+
+/* declares a char buffer[64] _dbuf, copies data from
+ * _b with length _l into it and ensures that _dbuf ends
+ * with a \0 character.
+ */
+#define DECLARE_BUF_AS_STRING(_dbuf, _b, _l) \
+ char _dbuf[64]; int dlen = (_l) < 0 ? 0 : (_l); \
+ if (dlen >= sizeof(_dbuf)) dlen = sizeof(_dbuf)-1; \
+ memcpy(_dbuf, _b, dlen); _dbuf[dlen] = 0
+
+static ssize_t kobj_pkt_show(struct kobject *kobj,
+ struct attribute *attr, char *data)
+{
+ struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd;
+ int n = 0;
+ int v;
+ if (strcmp(attr->name, "packets_started") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.pkt_started);
+
+ } else if (strcmp(attr->name, "packets_finished") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.pkt_ended);
+
+ } else if (strcmp(attr->name, "kb_written") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.secs_w >> 1);
+
+ } else if (strcmp(attr->name, "kb_read") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.secs_r >> 1);
+
+ } else if (strcmp(attr->name, "kb_read_gather") == 0) {
+ n = sprintf(data, "%lu\n", pd->stats.secs_rg >> 1);
+
+ } else if (strcmp(attr->name, "size") == 0) {
+ spin_lock(&pd->lock);
+ v = pd->bio_queue_size;
+ spin_unlock(&pd->lock);
+ n = sprintf(data, "%d\n", v);
+
+ } else if (strcmp(attr->name, "congestion_off") == 0) {
+ spin_lock(&pd->lock);
+ v = pd->write_congestion_off;
+ spin_unlock(&pd->lock);
+ n = sprintf(data, "%d\n", v);
+
+ } else if (strcmp(attr->name, "congestion_on") == 0) {
+ spin_lock(&pd->lock);
+ v = pd->write_congestion_on;
+ spin_unlock(&pd->lock);
+ n = sprintf(data, "%d\n", v);
+ }
+ return n;
+}
+
+static void init_write_congestion_marks(int* lo, int* hi)
+{
+ if (*hi > 0) {
+ *hi = max(*hi, 500);
+ *hi = min(*hi, 1000000);
+ if (*lo <= 0)
+ *lo = *hi - 100;
+ else {
+ *lo = min(*lo, *hi - 100);
+ *lo = max(*lo, 100);
+ }
+ } else {
+ *hi = -1;
+ *lo = -1;
+ }
+}
+
+static ssize_t kobj_pkt_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *data, size_t len)
+{
+ struct pktcdvd_device *pd = to_pktcdvdkobj(kobj)->pd;
+ int val;
+ DECLARE_BUF_AS_STRING(dbuf, data, len); /* ensure sscanf scans a string */
+
+ if (strcmp(attr->name, "reset") == 0 && dlen > 0) {
+ pd->stats.pkt_started = 0;
+ pd->stats.pkt_ended = 0;
+ pd->stats.secs_w = 0;
+ pd->stats.secs_rg = 0;
+ pd->stats.secs_r = 0;
+
+ } else if (strcmp(attr->name, "congestion_off") == 0
+ && sscanf(dbuf, "%d", &val) == 1) {
+ spin_lock(&pd->lock);
+ pd->write_congestion_off = val;
+ init_write_congestion_marks(&pd->write_congestion_off,
+ &pd->write_congestion_on);
+ spin_unlock(&pd->lock);
+
+ } else if (strcmp(attr->name, "congestion_on") == 0
+ && sscanf(dbuf, "%d", &val) == 1) {
+ spin_lock(&pd->lock);
+ pd->write_congestion_on = val;
+ init_write_congestion_marks(&pd->write_congestion_off,
+ &pd->write_congestion_on);
+ spin_unlock(&pd->lock);
+ }
+ return len;
+}
+
+static struct sysfs_ops kobj_pkt_ops = {
+ .show = kobj_pkt_show,
+ .store = kobj_pkt_store
+};
+static struct kobj_type kobj_pkt_type_stat = {
+ .release = pkt_kobj_release,
+ .sysfs_ops = &kobj_pkt_ops,
+ .default_attrs = kobj_pkt_attrs_stat
+};
+static struct kobj_type kobj_pkt_type_wqueue = {
+ .release = pkt_kobj_release,
+ .sysfs_ops = &kobj_pkt_ops,
+ .default_attrs = kobj_pkt_attrs_wqueue
+};
+
+static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
+{
+ if (class_pktcdvd) {
+ pd->clsdev = class_device_create(class_pktcdvd,
+ NULL, pd->pkt_dev,
+ NULL, "%s", pd->name);
+ if (IS_ERR(pd->clsdev))
+ pd->clsdev = NULL;
+ }
+ if (pd->clsdev) {
+ pd->kobj_stat = pkt_kobj_create(pd, "stat",
+ &pd->clsdev->kobj,
+ &kobj_pkt_type_stat);
+ pd->kobj_wqueue = pkt_kobj_create(pd, "write_queue",
+ &pd->clsdev->kobj,
+ &kobj_pkt_type_wqueue);
+ }
+}
+
+static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd)
+{
+ pkt_kobj_remove(pd->kobj_stat);
+ pkt_kobj_remove(pd->kobj_wqueue);
+ if (class_pktcdvd)
+ class_device_destroy(class_pktcdvd, pd->pkt_dev);
+}
+
+
+/********************************************************************
+ /sys/class/pktcdvd/
+ add map block device
+ remove unmap packet dev
+ device_map show mappings
+ *******************************************************************/
+
+static void class_pktcdvd_release(struct class *cls)
+{
+ kfree(cls);
+}
+static ssize_t class_pktcdvd_show_map(struct class *c, char *data)
+{
+ int n = 0;
+ int idx;
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+ for (idx = 0; idx < MAX_WRITERS; idx++) {
+ struct pktcdvd_device *pd = pkt_devs[idx];
+ if (!pd)
+ continue;
+ n += sprintf(data+n, "%s %u:%u %u:%u\n",
+ pd->name,
+ MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev),
+ MAJOR(pd->bdev->bd_dev),
+ MINOR(pd->bdev->bd_dev));
+ }
+ mutex_unlock(&ctl_mutex);
+ return n;
+}
+
+static ssize_t class_pktcdvd_store_add(struct class *c, const char *buf,
+ size_t count)
+{
+ unsigned int major, minor;
+ DECLARE_BUF_AS_STRING(dbuf, buf, count);
+ if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
+ pkt_setup_dev(MKDEV(major, minor), NULL);
+ return count;
+ }
+ return -EINVAL;
+}
+
+static ssize_t class_pktcdvd_store_remove(struct class *c, const char *buf,
+ size_t count)
+{
+ unsigned int major, minor;
+ DECLARE_BUF_AS_STRING(dbuf, buf, count);
+ if (sscanf(dbuf, "%u:%u", &major, &minor) == 2) {
+ pkt_remove_dev(MKDEV(major, minor));
+ return count;
+ }
+ return -EINVAL;
+}
+
+static struct class_attribute class_pktcdvd_attrs[] = {
+ __ATTR(add, 0200, NULL, class_pktcdvd_store_add),
+ __ATTR(remove, 0200, NULL, class_pktcdvd_store_remove),
+ __ATTR(device_map, 0444, class_pktcdvd_show_map, NULL),
+ __ATTR_NULL
+};
+
+
+static int pkt_sysfs_init(void)
+{
+ int ret = 0;
+
+ /*
+ * create control files in sysfs
+ * /sys/class/pktcdvd/...
+ */
+ class_pktcdvd = kzalloc(sizeof(*class_pktcdvd), GFP_KERNEL);
+ if (!class_pktcdvd)
+ return -ENOMEM;
+ class_pktcdvd->name = DRIVER_NAME;
+ class_pktcdvd->owner = THIS_MODULE;
+ class_pktcdvd->class_release = class_pktcdvd_release;
+ class_pktcdvd->class_attrs = class_pktcdvd_attrs;
+ ret = class_register(class_pktcdvd);
+ if (ret) {
+ kfree(class_pktcdvd);
+ class_pktcdvd = NULL;
+ printk(DRIVER_NAME": failed to create class pktcdvd\n");
+ return ret;
+ }
+ return 0;
+}
+
+static void pkt_sysfs_cleanup(void)
+{
+ if (class_pktcdvd)
+ class_destroy(class_pktcdvd);
+ class_pktcdvd = NULL;
+}
+
+/********************************************************************
+ entries in debugfs
+
+ /debugfs/pktcdvd[0-7]/
+ info
+
+ *******************************************************************/
+
+static int pkt_debugfs_seq_show(struct seq_file *m, void *p)
+{
+ return pkt_seq_show(m, p);
+}
+
+static int pkt_debugfs_fops_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, pkt_debugfs_seq_show, inode->i_private);
+}
+
+static struct file_operations debug_fops = {
+ .open = pkt_debugfs_fops_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .owner = THIS_MODULE,
+};
+
+static void pkt_debugfs_dev_new(struct pktcdvd_device *pd)
+{
+ if (!pkt_debugfs_root)
+ return;
+ pd->dfs_f_info = NULL;
+ pd->dfs_d_root = debugfs_create_dir(pd->name, pkt_debugfs_root);
+ if (IS_ERR(pd->dfs_d_root)) {
+ pd->dfs_d_root = NULL;
+ return;
+ }
+ pd->dfs_f_info = debugfs_create_file("info", S_IRUGO,
+ pd->dfs_d_root, pd, &debug_fops);
+ if (IS_ERR(pd->dfs_f_info)) {
+ pd->dfs_f_info = NULL;
+ return;
+ }
+}
+
+static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd)
+{
+ if (!pkt_debugfs_root)
+ return;
+ if (pd->dfs_f_info)
+ debugfs_remove(pd->dfs_f_info);
+ pd->dfs_f_info = NULL;
+ if (pd->dfs_d_root)
+ debugfs_remove(pd->dfs_d_root);
+ pd->dfs_d_root = NULL;
+}
+
+static void pkt_debugfs_init(void)
+{
+ pkt_debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL);
+ if (IS_ERR(pkt_debugfs_root)) {
+ pkt_debugfs_root = NULL;
+ return;
+ }
+}
+
+static void pkt_debugfs_cleanup(void)
+{
+ if (!pkt_debugfs_root)
+ return;
+ debugfs_remove(pkt_debugfs_root);
+ pkt_debugfs_root = NULL;
+}
+
+/* ----------------------------------------------------------*/
+
static void pkt_bio_finished(struct pktcdvd_device *pd)
{
BUG_ON(atomic_read(&pd->cdrw.pending_bios) <= 0);
if (atomic_dec_and_test(&pd->cdrw.pending_bios)) {
- VPRINTK("pktcdvd: queue empty\n");
+ VPRINTK(DRIVER_NAME": queue empty\n");
atomic_set(&pd->iosched.attention, 1);
wake_up(&pd->wqueue);
}
@@ -348,7 +768,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
char sense[SCSI_SENSE_BUFFERSIZE];
request_queue_t *q;
struct request *rq;
- DECLARE_COMPLETION(wait);
+ DECLARE_COMPLETION_ONSTACK(wait);
int err = 0;
q = bdev_get_queue(pd->bdev);
@@ -365,17 +785,17 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
rq->sense = sense;
memset(sense, 0, sizeof(sense));
rq->sense_len = 0;
- rq->flags |= REQ_BLOCK_PC | REQ_HARDBARRIER;
+ rq->cmd_type = REQ_TYPE_BLOCK_PC;
+ rq->cmd_flags |= REQ_HARDBARRIER;
if (cgc->quiet)
- rq->flags |= REQ_QUIET;
+ rq->cmd_flags |= REQ_QUIET;
memcpy(rq->cmd, cgc->cmd, CDROM_PACKET_SIZE);
if (sizeof(rq->cmd) > CDROM_PACKET_SIZE)
memset(rq->cmd + CDROM_PACKET_SIZE, 0, sizeof(rq->cmd) - CDROM_PACKET_SIZE);
rq->cmd_len = COMMAND_SIZE(rq->cmd[0]);
rq->ref_count++;
- rq->flags |= REQ_NOMERGE;
- rq->waiting = &wait;
+ rq->end_io_data = &wait;
rq->end_io = blk_end_sync_rq;
elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
generic_unplug_device(q);
@@ -400,7 +820,7 @@ static void pkt_dump_sense(struct packet_command *cgc)
int i;
struct request_sense *sense = cgc->sense;
- printk("pktcdvd:");
+ printk(DRIVER_NAME":");
for (i = 0; i < CDROM_PACKET_SIZE; i++)
printk(" %02x", cgc->cmd[i]);
printk(" - ");
@@ -528,7 +948,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
need_write_seek = 0;
if (need_write_seek && reads_queued) {
if (atomic_read(&pd->cdrw.pending_bios) > 0) {
- VPRINTK("pktcdvd: write, waiting\n");
+ VPRINTK(DRIVER_NAME": write, waiting\n");
break;
}
pkt_flush_cache(pd);
@@ -537,7 +957,7 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
} else {
if (!reads_queued && writes_queued) {
if (atomic_read(&pd->cdrw.pending_bios) > 0) {
- VPRINTK("pktcdvd: read, waiting\n");
+ VPRINTK(DRIVER_NAME": read, waiting\n");
break;
}
pd->iosched.writing = 1;
@@ -600,7 +1020,7 @@ static int pkt_set_segment_merging(struct pktcdvd_device *pd, request_queue_t *q
set_bit(PACKET_MERGE_SEGS, &pd->flags);
return 0;
} else {
- printk("pktcdvd: cdrom max_phys_segments too small\n");
+ printk(DRIVER_NAME": cdrom max_phys_segments too small\n");
return -EIO;
}
}
@@ -891,6 +1311,7 @@ static int pkt_handle_queue(struct pktcdvd_device *pd)
sector_t zone = 0; /* Suppress gcc warning */
struct pkt_rb_node *node, *first_node;
struct rb_node *n;
+ int wakeup;
VPRINTK("handle_queue\n");
@@ -963,7 +1384,13 @@ try_next_bio:
pkt->write_size += bio->bi_size / CD_FRAMESIZE;
spin_unlock(&pkt->lock);
}
+ /* check write congestion marks, and if bio_queue_size is
+ below, wake up any waiters */
+ wakeup = (pd->write_congestion_on > 0
+ && pd->bio_queue_size <= pd->write_congestion_off);
spin_unlock(&pd->lock);
+ if (wakeup)
+ blk_clear_queue_congested(pd->disk->queue, WRITE);
pkt->sleep_time = max(PACKET_WAIT_TIME, 1);
pkt_set_state(pkt, PACKET_WAITING_STATE);
@@ -1049,7 +1476,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
for (f = 0; f < pkt->frames; f++)
if (!bio_add_page(pkt->w_bio, bvec[f].bv_page, CD_FRAMESIZE, bvec[f].bv_offset))
BUG();
- VPRINTK("pktcdvd: vcnt=%d\n", pkt->w_bio->bi_vcnt);
+ VPRINTK(DRIVER_NAME": vcnt=%d\n", pkt->w_bio->bi_vcnt);
atomic_set(&pkt->io_wait, 1);
pkt->w_bio->bi_rw = WRITE;
@@ -1286,7 +1713,7 @@ work_to_do:
static void pkt_print_settings(struct pktcdvd_device *pd)
{
- printk("pktcdvd: %s packets, ", pd->settings.fp ? "Fixed" : "Variable");
+ printk(DRIVER_NAME": %s packets, ", pd->settings.fp ? "Fixed" : "Variable");
printk("%u blocks, ", pd->settings.size >> 2);
printk("Mode-%c disc\n", pd->settings.block_mode == 8 ? '1' : '2');
}
@@ -1471,7 +1898,7 @@ static int pkt_set_write_settings(struct pktcdvd_device *pd)
/*
* paranoia
*/
- printk("pktcdvd: write mode wrong %d\n", wp->data_block_type);
+ printk(DRIVER_NAME": write mode wrong %d\n", wp->data_block_type);
return 1;
}
wp->packet_size = cpu_to_be32(pd->settings.size >> 2);
@@ -1515,7 +1942,7 @@ static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
if (ti->rt == 1 && ti->blank == 0)
return 1;
- printk("pktcdvd: bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
+ printk(DRIVER_NAME": bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
return 0;
}
@@ -1533,7 +1960,7 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
case 0x12: /* DVD-RAM */
return 1;
default:
- VPRINTK("pktcdvd: Wrong disc profile (%x)\n", pd->mmc3_profile);
+ VPRINTK(DRIVER_NAME": Wrong disc profile (%x)\n", pd->mmc3_profile);
return 0;
}
@@ -1542,22 +1969,22 @@ static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
* but i'm not sure, should we leave this to user apps? probably.
*/
if (di->disc_type == 0xff) {
- printk("pktcdvd: Unknown disc. No track?\n");
+ printk(DRIVER_NAME": Unknown disc. No track?\n");
return 0;
}
if (di->disc_type != 0x20 && di->disc_type != 0) {
- printk("pktcdvd: Wrong disc type (%x)\n", di->disc_type);
+ printk(DRIVER_NAME": Wrong disc type (%x)\n", di->disc_type);
return 0;
}
if (di->erasable == 0) {
- printk("pktcdvd: Disc not erasable\n");
+ printk(DRIVER_NAME": Disc not erasable\n");
return 0;
}
if (di->border_status == PACKET_SESSION_RESERVED) {
- printk("pktcdvd: Can't write to last track (reserved)\n");
+ printk(DRIVER_NAME": Can't write to last track (reserved)\n");
return 0;
}
@@ -1593,12 +2020,12 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
track = 1; /* (di.last_track_msb << 8) | di.last_track_lsb; */
if ((ret = pkt_get_track_info(pd, track, 1, &ti))) {
- printk("pktcdvd: failed get_track\n");
+ printk(DRIVER_NAME": failed get_track\n");
return ret;
}
if (!pkt_writable_track(pd, &ti)) {
- printk("pktcdvd: can't write to this track\n");
+ printk(DRIVER_NAME": can't write to this track\n");
return -EROFS;
}
@@ -1608,11 +2035,11 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
*/
pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2;
if (pd->settings.size == 0) {
- printk("pktcdvd: detected zero packet size!\n");
+ printk(DRIVER_NAME": detected zero packet size!\n");
return -ENXIO;
}
if (pd->settings.size > PACKET_MAX_SECTORS) {
- printk("pktcdvd: packet size is too big\n");
+ printk(DRIVER_NAME": packet size is too big\n");
return -EROFS;
}
pd->settings.fp = ti.fp;
@@ -1654,7 +2081,7 @@ static int pkt_probe_settings(struct pktcdvd_device *pd)
pd->settings.block_mode = PACKET_BLOCK_MODE2;
break;
default:
- printk("pktcdvd: unknown data mode\n");
+ printk(DRIVER_NAME": unknown data mode\n");
return -EROFS;
}
return 0;
@@ -1688,10 +2115,10 @@ static int pkt_write_caching(struct pktcdvd_device *pd, int set)
cgc.buflen = cgc.cmd[8] = 2 + ((buf[0] << 8) | (buf[1] & 0xff));
ret = pkt_mode_select(pd, &cgc);
if (ret) {
- printk("pktcdvd: write caching control failed\n");
+ printk(DRIVER_NAME": write caching control failed\n");
pkt_dump_sense(&cgc);
} else if (!ret && set)
- printk("pktcdvd: enabled write caching on %s\n", pd->name);
+ printk(DRIVER_NAME": enabled write caching on %s\n", pd->name);
return ret;
}
@@ -1805,11 +2232,11 @@ static int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed)
}
if (!buf[6] & 0x40) {
- printk("pktcdvd: Disc type is not CD-RW\n");
+ printk(DRIVER_NAME": Disc type is not CD-RW\n");
return 1;
}
if (!buf[6] & 0x4) {
- printk("pktcdvd: A1 values on media are not valid, maybe not CDRW?\n");
+ printk(DRIVER_NAME": A1 values on media are not valid, maybe not CDRW?\n");
return 1;
}
@@ -1829,14 +2256,14 @@ static int pkt_media_speed(struct pktcdvd_device *pd, unsigned *speed)
*speed = us_clv_to_speed[sp];
break;
default:
- printk("pktcdvd: Unknown disc sub-type %d\n",st);
+ printk(DRIVER_NAME": Unknown disc sub-type %d\n",st);
return 1;
}
if (*speed) {
- printk("pktcdvd: Max. media speed: %d\n",*speed);
+ printk(DRIVER_NAME": Max. media speed: %d\n",*speed);
return 0;
} else {
- printk("pktcdvd: Unknown speed %d for sub-type %d\n",sp,st);
+ printk(DRIVER_NAME": Unknown speed %d for sub-type %d\n",sp,st);
return 1;
}
}
@@ -1847,7 +2274,7 @@ static int pkt_perform_opc(struct pktcdvd_device *pd)
struct request_sense sense;
int ret;
- VPRINTK("pktcdvd: Performing OPC\n");
+ VPRINTK(DRIVER_NAME": Performing OPC\n");
init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
cgc.sense = &sense;
@@ -1865,12 +2292,12 @@ static int pkt_open_write(struct pktcdvd_device *pd)
unsigned int write_speed, media_write_speed, read_speed;
if ((ret = pkt_probe_settings(pd))) {
- VPRINTK("pktcdvd: %s failed probe\n", pd->name);
+ VPRINTK(DRIVER_NAME": %s failed probe\n", pd->name);
return ret;
}
if ((ret = pkt_set_write_settings(pd))) {
- DPRINTK("pktcdvd: %s failed saving write settings\n", pd->name);
+ DPRINTK(DRIVER_NAME": %s failed saving write settings\n", pd->name);
return -EIO;
}
@@ -1882,26 +2309,26 @@ static int pkt_open_write(struct pktcdvd_device *pd)
case 0x13: /* DVD-RW */
case 0x1a: /* DVD+RW */
case 0x12: /* DVD-RAM */
- DPRINTK("pktcdvd: write speed %ukB/s\n", write_speed);
+ DPRINTK(DRIVER_NAME": write speed %ukB/s\n", write_speed);
break;
default:
if ((ret = pkt_media_speed(pd, &media_write_speed)))
media_write_speed = 16;
write_speed = min(write_speed, media_write_speed * 177);
- DPRINTK("pktcdvd: write speed %ux\n", write_speed / 176);
+ DPRINTK(DRIVER_NAME": write speed %ux\n", write_speed / 176);
break;
}
read_speed = write_speed;
if ((ret = pkt_set_speed(pd, write_speed, read_speed))) {
- DPRINTK("pktcdvd: %s couldn't set write speed\n", pd->name);
+ DPRINTK(DRIVER_NAME": %s couldn't set write speed\n", pd->name);
return -EIO;
}
pd->write_speed = write_speed;
pd->read_speed = read_speed;
if ((ret = pkt_perform_opc(pd))) {
- DPRINTK("pktcdvd: %s Optimum Power Calibration failed\n", pd->name);
+ DPRINTK(DRIVER_NAME": %s Optimum Power Calibration failed\n", pd->name);
}
return 0;
@@ -1929,7 +2356,7 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
goto out_putdev;
if ((ret = pkt_get_last_written(pd, &lba))) {
- printk("pktcdvd: pkt_get_last_written failed\n");
+ printk(DRIVER_NAME": pkt_get_last_written failed\n");
goto out_unclaim;
}
@@ -1959,11 +2386,11 @@ static int pkt_open_dev(struct pktcdvd_device *pd, int write)
if (write) {
if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
- printk("pktcdvd: not enough memory for buffers\n");
+ printk(DRIVER_NAME": not enough memory for buffers\n");
ret = -ENOMEM;
goto out_unclaim;
}
- printk("pktcdvd: %lukB available on disc\n", lba << 1);
+ printk(DRIVER_NAME": %lukB available on disc\n", lba << 1);
}
return 0;
@@ -1983,7 +2410,7 @@ out:
static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
{
if (flush && pkt_flush_cache(pd))
- DPRINTK("pktcdvd: %s not flushing cache\n", pd->name);
+ DPRINTK(DRIVER_NAME": %s not flushing cache\n", pd->name);
pkt_lock_door(pd, 0);
@@ -2006,7 +2433,7 @@ static int pkt_open(struct inode *inode, struct file *file)
struct pktcdvd_device *pd = NULL;
int ret;
- VPRINTK("pktcdvd: entering open\n");
+ VPRINTK(DRIVER_NAME": entering open\n");
mutex_lock(&ctl_mutex);
pd = pkt_find_dev_from_minor(iminor(inode));
@@ -2040,7 +2467,7 @@ static int pkt_open(struct inode *inode, struct file *file)
out_dec:
pd->refcnt--;
out:
- VPRINTK("pktcdvd: failed open (%d)\n", ret);
+ VPRINTK(DRIVER_NAME": failed open (%d)\n", ret);
mutex_unlock(&ctl_mutex);
return ret;
}
@@ -2088,7 +2515,7 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
pd = q->queuedata;
if (!pd) {
- printk("pktcdvd: %s incorrect request queue\n", bdevname(bio->bi_bdev, b));
+ printk(DRIVER_NAME": %s incorrect request queue\n", bdevname(bio->bi_bdev, b));
goto end_io;
}
@@ -2110,13 +2537,13 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
}
if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
- printk("pktcdvd: WRITE for ro device %s (%llu)\n",
+ printk(DRIVER_NAME": WRITE for ro device %s (%llu)\n",
pd->name, (unsigned long long)bio->bi_sector);
goto end_io;
}
if (!bio->bi_size || (bio->bi_size % CD_FRAMESIZE)) {
- printk("pktcdvd: wrong bio size\n");
+ printk(DRIVER_NAME": wrong bio size\n");
goto end_io;
}
@@ -2176,6 +2603,23 @@ static int pkt_make_request(request_queue_t *q, struct bio *bio)
}
spin_unlock(&pd->cdrw.active_list_lock);
+ /*
+ * Test if there is enough room left in the bio work queue
+ * (queue size >= congestion on mark).
+ * If not, wait till the work queue size is below the congestion off mark.
+ */
+ spin_lock(&pd->lock);
+ if (pd->write_congestion_on > 0
+ && pd->bio_queue_size >= pd->write_congestion_on) {
+ blk_set_queue_congested(q, WRITE);
+ do {
+ spin_unlock(&pd->lock);
+ congestion_wait(WRITE, HZ);
+ spin_lock(&pd->lock);
+ } while(pd->bio_queue_size > pd->write_congestion_off);
+ }
+ spin_unlock(&pd->lock);
+
/*
* No matching packet found. Store the bio in the work queue.
*/
@@ -2295,6 +2739,9 @@ static int pkt_seq_show(struct seq_file *m, void *p)
seq_printf(m, "\tstate:\t\t\ti:%d ow:%d rw:%d ww:%d rec:%d fin:%d\n",
states[0], states[1], states[2], states[3], states[4], states[5]);
+ seq_printf(m, "\twrite congestion marks:\toff=%d on=%d\n",
+ pd->write_congestion_off,
+ pd->write_congestion_on);
return 0;
}
@@ -2319,7 +2766,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
struct block_device *bdev;
if (pd->pkt_dev == dev) {
- printk("pktcdvd: Recursive setup not allowed\n");
+ printk(DRIVER_NAME": Recursive setup not allowed\n");
return -EBUSY;
}
for (i = 0; i < MAX_WRITERS; i++) {
@@ -2327,11 +2774,11 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
if (!pd2)
continue;
if (pd2->bdev->bd_dev == dev) {
- printk("pktcdvd: %s already setup\n", bdevname(pd2->bdev, b));
+ printk(DRIVER_NAME": %s already setup\n", bdevname(pd2->bdev, b));
return -EBUSY;
}
if (pd2->pkt_dev == dev) {
- printk("pktcdvd: Can't chain pktcdvd devices\n");
+ printk(DRIVER_NAME": Can't chain pktcdvd devices\n");
return -EBUSY;
}
}
@@ -2354,7 +2801,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
atomic_set(&pd->cdrw.pending_bios, 0);
pd->cdrw.thread = kthread_run(kcdrwd, pd, "%s", pd->name);
if (IS_ERR(pd->cdrw.thread)) {
- printk("pktcdvd: can't start kernel thread\n");
+ printk(DRIVER_NAME": can't start kernel thread\n");
ret = -ENOMEM;
goto out_mem;
}
@@ -2364,7 +2811,7 @@ static int pkt_new_dev(struct pktcdvd_device *pd, dev_t dev)
proc->data = pd;
proc->proc_fops = &pkt_proc_fops;
}
- DPRINTK("pktcdvd: writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
+ DPRINTK(DRIVER_NAME": writer %s mapped to %s\n", pd->name, bdevname(bdev, b));
return 0;
out_mem:
@@ -2401,7 +2848,7 @@ static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg);
default:
- VPRINTK("pktcdvd: Unknown ioctl for %s (%x)\n", pd->name, cmd);
+ VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd);
return -ENOTTY;
}
@@ -2434,51 +2881,55 @@ static struct block_device_operations pktcdvd_ops = {
/*
* Set up mapping from pktcdvd device to CD-ROM device.
*/
-static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
+static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
{
int idx;
int ret = -ENOMEM;
struct pktcdvd_device *pd;
struct gendisk *disk;
- dev_t dev = new_decode_dev(ctrl_cmd->dev);
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
for (idx = 0; idx < MAX_WRITERS; idx++)
if (!pkt_devs[idx])
break;
if (idx == MAX_WRITERS) {
- printk("pktcdvd: max %d writers supported\n", MAX_WRITERS);
- return -EBUSY;
+ printk(DRIVER_NAME": max %d writers supported\n", MAX_WRITERS);
+ ret = -EBUSY;
+ goto out_mutex;
}
pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
if (!pd)
- return ret;
+ goto out_mutex;
pd->rb_pool = mempool_create_kmalloc_pool(PKT_RB_POOL_SIZE,
sizeof(struct pkt_rb_node));
if (!pd->rb_pool)
goto out_mem;
- disk = alloc_disk(1);
- if (!disk)
- goto out_mem;
- pd->disk = disk;
-
INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
spin_lock_init(&pd->cdrw.active_list_lock);
spin_lock_init(&pd->lock);
spin_lock_init(&pd->iosched.lock);
- sprintf(pd->name, "pktcdvd%d", idx);
+ sprintf(pd->name, DRIVER_NAME"%d", idx);
init_waitqueue_head(&pd->wqueue);
pd->bio_queue = RB_ROOT;
- disk->major = pkt_major;
+ pd->write_congestion_on = write_congestion_on;
+ pd->write_congestion_off = write_congestion_off;
+
+ disk = alloc_disk(1);
+ if (!disk)
+ goto out_mem;
+ pd->disk = disk;
+ disk->major = pktdev_major;
disk->first_minor = idx;
disk->fops = &pktcdvd_ops;
disk->flags = GENHD_FL_REMOVABLE;
- sprintf(disk->disk_name, "pktcdvd%d", idx);
+ strcpy(disk->disk_name, pd->name);
disk->private_data = pd;
disk->queue = blk_alloc_queue(GFP_KERNEL);
if (!disk->queue)
@@ -2490,8 +2941,15 @@ static int pkt_setup_dev(struct pkt_ctrl_command *ctrl_cmd)
goto out_new_dev;
add_disk(disk);
+
+ pkt_sysfs_dev_new(pd);
+ pkt_debugfs_dev_new(pd);
+
pkt_devs[idx] = pd;
- ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev);
+ if (pkt_dev)
+ *pkt_dev = pd->pkt_dev;
+
+ mutex_unlock(&ctl_mutex);
return 0;
out_new_dev:
@@ -2502,17 +2960,22 @@ out_mem:
if (pd->rb_pool)
mempool_destroy(pd->rb_pool);
kfree(pd);
+out_mutex:
+ mutex_unlock(&ctl_mutex);
+ printk(DRIVER_NAME": setup of pktcdvd device failed\n");
return ret;
}
/*
* Tear down mapping from pktcdvd device to CD-ROM device.
*/
-static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
+static int pkt_remove_dev(dev_t pkt_dev)
{
struct pktcdvd_device *pd;
int idx;
- dev_t pkt_dev = new_decode_dev(ctrl_cmd->pkt_dev);
+ int ret = 0;
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
for (idx = 0; idx < MAX_WRITERS; idx++) {
pd = pkt_devs[idx];
@@ -2520,37 +2983,50 @@ static int pkt_remove_dev(struct pkt_ctrl_command *ctrl_cmd)
break;
}
if (idx == MAX_WRITERS) {
- DPRINTK("pktcdvd: dev not setup\n");
- return -ENXIO;
+ DPRINTK(DRIVER_NAME": dev not setup\n");
+ ret = -ENXIO;
+ goto out;
}
- if (pd->refcnt > 0)
- return -EBUSY;
-
+ if (pd->refcnt > 0) {
+ ret = -EBUSY;
+ goto out;
+ }
if (!IS_ERR(pd->cdrw.thread))
kthread_stop(pd->cdrw.thread);
+ pkt_devs[idx] = NULL;
+
+ pkt_debugfs_dev_remove(pd);
+ pkt_sysfs_dev_remove(pd);
+
blkdev_put(pd->bdev);
remove_proc_entry(pd->name, pkt_proc);
- DPRINTK("pktcdvd: writer %s unmapped\n", pd->name);
+ DPRINTK(DRIVER_NAME": writer %s unmapped\n", pd->name);
del_gendisk(pd->disk);
blk_cleanup_queue(pd->disk->queue);
put_disk(pd->disk);
- pkt_devs[idx] = NULL;
mempool_destroy(pd->rb_pool);
kfree(pd);
/* This is safe: open() is still holding a reference. */
module_put(THIS_MODULE);
- return 0;
+
+out:
+ mutex_unlock(&ctl_mutex);
+ return ret;
}
static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)
{
- struct pktcdvd_device *pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index);
+ struct pktcdvd_device *pd;
+
+ mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+
+ pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index);
if (pd) {
ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev);
ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev);
@@ -2559,6 +3035,8 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)
ctrl_cmd->pkt_dev = 0;
}
ctrl_cmd->num_devices = MAX_WRITERS;
+
+ mutex_unlock(&ctl_mutex);
}
static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -2566,6 +3044,7 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
void __user *argp = (void __user *)arg;
struct pkt_ctrl_command ctrl_cmd;
int ret = 0;
+ dev_t pkt_dev = 0;
if (cmd != PACKET_CTRL_CMD)
return -ENOTTY;
@@ -2577,21 +3056,16 @@ static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cm
case PKT_CTRL_CMD_SETUP:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
- ret = pkt_setup_dev(&ctrl_cmd);
- mutex_unlock(&ctl_mutex);
+ ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev);
+ ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev);
break;
case PKT_CTRL_CMD_TEARDOWN:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
- ret = pkt_remove_dev(&ctrl_cmd);
- mutex_unlock(&ctl_mutex);
+ ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev));
break;
case PKT_CTRL_CMD_STATUS:
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
pkt_get_status(&ctrl_cmd);
- mutex_unlock(&ctl_mutex);
break;
default:
return -ENOTTY;
@@ -2610,7 +3084,7 @@ static struct file_operations pkt_ctl_fops = {
static struct miscdevice pkt_misc = {
.minor = MISC_DYNAMIC_MINOR,
- .name = "pktcdvd",
+ .name = DRIVER_NAME,
.fops = &pkt_ctl_fops
};
@@ -2618,33 +3092,42 @@ static int __init pkt_init(void)
{
int ret;
+ mutex_init(&ctl_mutex);
+
psd_pool = mempool_create_kmalloc_pool(PSD_POOL_SIZE,
sizeof(struct packet_stacked_data));
if (!psd_pool)
return -ENOMEM;
- ret = register_blkdev(pkt_major, "pktcdvd");
+ ret = register_blkdev(pktdev_major, DRIVER_NAME);
if (ret < 0) {
- printk("pktcdvd: Unable to register block device\n");
+ printk(DRIVER_NAME": Unable to register block device\n");
goto out2;
}
- if (!pkt_major)
- pkt_major = ret;
+ if (!pktdev_major)
+ pktdev_major = ret;
+
+ ret = pkt_sysfs_init();
+ if (ret)
+ goto out;
+
+ pkt_debugfs_init();
ret = misc_register(&pkt_misc);
if (ret) {
- printk("pktcdvd: Unable to register misc device\n");
- goto out;
+ printk(DRIVER_NAME": Unable to register misc device\n");
+ goto out_misc;
}
- mutex_init(&ctl_mutex);
-
- pkt_proc = proc_mkdir("pktcdvd", proc_root_driver);
+ pkt_proc = proc_mkdir(DRIVER_NAME, proc_root_driver);
return 0;
+out_misc:
+ pkt_debugfs_cleanup();
+ pkt_sysfs_cleanup();
out:
- unregister_blkdev(pkt_major, "pktcdvd");
+ unregister_blkdev(pktdev_major, DRIVER_NAME);
out2:
mempool_destroy(psd_pool);
return ret;
@@ -2652,9 +3135,13 @@ out2:
static void __exit pkt_exit(void)
{
- remove_proc_entry("pktcdvd", proc_root_driver);
+ remove_proc_entry(DRIVER_NAME, proc_root_driver);
misc_deregister(&pkt_misc);
- unregister_blkdev(pkt_major, "pktcdvd");
+
+ pkt_debugfs_cleanup();
+ pkt_sysfs_cleanup();
+
+ unregister_blkdev(pktdev_major, DRIVER_NAME);
mempool_destroy(psd_pool);
}
diff --git a/drivers/block/ps2esdi.c b/drivers/block/ps2esdi.c
index 5537974fb24..688a4fb0dc9 100644
--- a/drivers/block/ps2esdi.c
+++ b/drivers/block/ps2esdi.c
@@ -75,8 +75,7 @@ static int ps2esdi_out_cmd_blk(u_short * cmd_blk);
static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode);
-static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id,
- struct pt_regs *regs);
+static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id);
static void (*current_int_handler) (u_int) = NULL;
static void ps2esdi_normal_interrupt_handler(u_int);
static void ps2esdi_initial_reset_int_handler(u_int);
@@ -687,8 +686,7 @@ static void ps2esdi_prep_dma(char *buffer, u_short length, u_char dma_xmode)
-static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t ps2esdi_interrupt_handler(int irq, void *dev_id)
{
u_int int_ret_code;
diff --git a/drivers/block/rd.c b/drivers/block/rd.c
index a3f64bfe6b5..485aa87e9bc 100644
--- a/drivers/block/rd.c
+++ b/drivers/block/rd.c
@@ -432,6 +432,12 @@ static int __init rd_init(void)
rd_disks[i] = alloc_disk(1);
if (!rd_disks[i])
goto out;
+
+ rd_queue[i] = blk_alloc_queue(GFP_KERNEL);
+ if (!rd_queue[i]) {
+ put_disk(rd_disks[i]);
+ goto out;
+ }
}
if (register_blkdev(RAMDISK_MAJOR, "ramdisk")) {
@@ -442,10 +448,6 @@ static int __init rd_init(void)
for (i = 0; i < CONFIG_BLK_DEV_RAM_COUNT; i++) {
struct gendisk *disk = rd_disks[i];
- rd_queue[i] = blk_alloc_queue(GFP_KERNEL);
- if (!rd_queue[i])
- goto out_queue;
-
blk_queue_make_request(rd_queue[i], &rd_make_request);
blk_queue_hardsect_size(rd_queue[i], rd_blocksize);
@@ -466,8 +468,6 @@ static int __init rd_init(void)
CONFIG_BLK_DEV_RAM_COUNT, rd_size, rd_blocksize);
return 0;
-out_queue:
- unregister_blkdev(RAMDISK_MAJOR, "ramdisk");
out:
while (i--) {
put_disk(rd_disks[i]);
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index cc42e762396..1a65979f1f0 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -238,8 +238,8 @@ static void scan_timeout(unsigned long data);
static void seek_timeout(unsigned long data);
static void settle_timeout(unsigned long data);
static void xfer_timeout(unsigned long data);
-static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-/*static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs);*/
+static irqreturn_t swim3_interrupt(int irq, void *dev_id);
+/*static void fd_dma_interrupt(int irq, void *dev_id);*/
static int grab_drive(struct floppy_state *fs, enum swim_state state,
int interruptible);
static void release_drive(struct floppy_state *fs);
@@ -319,8 +319,8 @@ static void start_request(struct floppy_state *fs)
printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
req->rq_disk->disk_name, req->cmd,
(long)req->sector, req->nr_sectors, req->buffer);
- printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n",
- req->rq_status, req->errors, req->current_nr_sectors);
+ printk(" errors=%d current_nr_sectors=%ld\n",
+ req->errors, req->current_nr_sectors);
#endif
if (req->sector < 0 || req->sector >= fs->total_secs) {
@@ -624,7 +624,7 @@ static void xfer_timeout(unsigned long data)
start_request(fs);
}
-static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t swim3_interrupt(int irq, void *dev_id)
{
struct floppy_state *fs = (struct floppy_state *) dev_id;
struct swim3 __iomem *sw = fs->swim3;
@@ -636,7 +636,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
intr = in_8(&sw->intr);
err = (intr & ERROR_INTR)? in_8(&sw->error): 0;
if ((intr & ERROR_INTR) && fs->state != do_transfer)
- printk(KERN_ERR "swim3_interrupt, state=%d, dir=%lx, intr=%x, err=%x\n",
+ printk(KERN_ERR "swim3_interrupt, state=%d, dir=%x, intr=%x, err=%x\n",
fs->state, rq_data_dir(fd_req), intr, err);
switch (fs->state) {
case locating:
@@ -742,7 +742,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if ((stat & ACTIVE) == 0 || resid != 0) {
/* musta been an error */
printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid);
- printk(KERN_ERR " state=%d, dir=%lx, intr=%x, err=%x\n",
+ printk(KERN_ERR " state=%d, dir=%x, intr=%x, err=%x\n",
fs->state, rq_data_dir(fd_req), intr, err);
end_request(fd_req, 0);
fs->state = idle;
@@ -777,7 +777,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
}
/*
-static void fd_dma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void fd_dma_interrupt(int irq, void *dev_id)
{
}
*/
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index 89e3c2f8b77..ed7b06cf3e6 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -94,7 +94,7 @@ static char *drive_names[7] = {
int swimiop_init(void);
static void swimiop_init_request(struct swim_iop_req *);
static int swimiop_send_request(struct swim_iop_req *);
-static void swimiop_receive(struct iop_msg *, struct pt_regs *);
+static void swimiop_receive(struct iop_msg *);
static void swimiop_status_update(int, struct swim_drvstatus *);
static int swimiop_eject(struct floppy_state *fs);
@@ -257,7 +257,7 @@ static int swimiop_send_request(struct swim_iop_req *req)
* 2. An unsolicited message was received from the IOP.
*/
-void swimiop_receive(struct iop_msg *msg, struct pt_regs *regs)
+void swimiop_receive(struct iop_msg *msg)
{
struct swim_iop_req *req;
struct swimmsg_status *sm;
@@ -529,8 +529,8 @@ static void start_request(struct floppy_state *fs)
printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n",
CURRENT->rq_disk->disk_name, CURRENT->cmd,
CURRENT->sector, CURRENT->nr_sectors, CURRENT->buffer);
- printk(" rq_status=%d errors=%d current_nr_sectors=%ld\n",
- CURRENT->rq_status, CURRENT->errors, CURRENT->current_nr_sectors);
+ printk(" errors=%d current_nr_sectors=%ld\n",
+ CURRENT->errors, CURRENT->current_nr_sectors);
#endif
if (CURRENT->sector < 0 || CURRENT->sector >= fs->total_secs) {
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index c6beee18a07..54509eb3391 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -1200,7 +1200,7 @@ static inline void carm_handle_responses(struct carm_host *host)
host->resp_idx += work;
}
-static irqreturn_t carm_interrupt(int irq, void *__host, struct pt_regs *regs)
+static irqreturn_t carm_interrupt(int irq, void *__host)
{
struct carm_host *host = __host;
void __iomem *mmio;
@@ -1244,9 +1244,10 @@ out:
return IRQ_RETVAL(handled);
}
-static void carm_fsm_task (void *_data)
+static void carm_fsm_task (struct work_struct *work)
{
- struct carm_host *host = _data;
+ struct carm_host *host =
+ container_of(work, struct carm_host, fsm_task);
unsigned long flags;
unsigned int state;
int rc, i, next_dev;
@@ -1619,7 +1620,7 @@ static int carm_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
host->pdev = pdev;
host->flags = pci_dac ? FL_DAC : 0;
spin_lock_init(&host->lock);
- INIT_WORK(&host->fsm_task, carm_fsm_task, host);
+ INIT_WORK(&host->fsm_task, carm_fsm_task);
init_completion(&host->probe_comp);
for (i = 0; i < ARRAY_SIZE(host->req); i++)
diff --git a/drivers/block/ub.c b/drivers/block/ub.c
index d62b49fbf10..2098eff91e1 100644
--- a/drivers/block/ub.c
+++ b/drivers/block/ub.c
@@ -358,11 +358,11 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct ub_request *urq);
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_end_rq(struct request *rq, int uptodate);
+static void ub_end_rq(struct request *rq, unsigned int status);
static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
struct ub_request *urq, struct ub_scsi_cmd *cmd);
static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
-static void ub_urb_complete(struct urb *urb, struct pt_regs *pt);
+static void ub_urb_complete(struct urb *urb);
static void ub_scsi_action(unsigned long _dev);
static void ub_scsi_dispatch(struct ub_dev *sc);
static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -376,7 +376,7 @@ static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
int stalled_pipe);
static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
static void ub_reset_enter(struct ub_dev *sc, int try);
-static void ub_reset_task(void *arg);
+static void ub_reset_task(struct work_struct *work);
static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
struct ub_capacity *ret);
@@ -639,9 +639,15 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
struct ub_request *urq;
int n_elem;
- if (atomic_read(&sc->poison) || lun->changed) {
+ if (atomic_read(&sc->poison)) {
+ blkdev_dequeue_request(rq);
+ ub_end_rq(rq, DID_NO_CONNECT << 16);
+ return 0;
+ }
+
+ if (lun->changed && !blk_pc_request(rq)) {
blkdev_dequeue_request(rq);
- ub_end_rq(rq, 0);
+ ub_end_rq(rq, SAM_STAT_CHECK_CONDITION);
return 0;
}
@@ -693,7 +699,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
drop:
ub_put_cmd(lun, cmd);
- ub_end_rq(rq, 0);
+ ub_end_rq(rq, DID_ERROR << 16);
return 0;
}
@@ -761,47 +767,53 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
struct ub_lun *lun = cmd->lun;
struct ub_request *urq = cmd->back;
struct request *rq;
- int uptodate;
+ unsigned int scsi_status;
rq = urq->rq;
if (cmd->error == 0) {
- uptodate = 1;
-
if (blk_pc_request(rq)) {
if (cmd->act_len >= rq->data_len)
rq->data_len = 0;
else
rq->data_len -= cmd->act_len;
}
+ scsi_status = 0;
} else {
- uptodate = 0;
-
if (blk_pc_request(rq)) {
/* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
rq->sense_len = UB_SENSE_SIZE;
if (sc->top_sense[0] != 0)
- rq->errors = SAM_STAT_CHECK_CONDITION;
+ scsi_status = SAM_STAT_CHECK_CONDITION;
else
- rq->errors = DID_ERROR << 16;
+ scsi_status = DID_ERROR << 16;
} else {
if (cmd->error == -EIO) {
if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
return;
}
+ scsi_status = SAM_STAT_CHECK_CONDITION;
}
}
urq->rq = NULL;
ub_put_cmd(lun, cmd);
- ub_end_rq(rq, uptodate);
+ ub_end_rq(rq, scsi_status);
blk_start_queue(lun->disk->queue);
}
-static void ub_end_rq(struct request *rq, int uptodate)
+static void ub_end_rq(struct request *rq, unsigned int scsi_status)
{
+ int uptodate;
+
+ if (scsi_status == 0) {
+ uptodate = 1;
+ } else {
+ uptodate = 0;
+ rq->errors = scsi_status;
+ }
end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
end_that_request_last(rq, uptodate);
}
@@ -947,7 +959,7 @@ static void ub_urb_timeout(unsigned long arg)
* the sc->lock taken) and from an interrupt (while we do NOT have
* the sc->lock taken). Therefore, bounce this off to a tasklet.
*/
-static void ub_urb_complete(struct urb *urb, struct pt_regs *pt)
+static void ub_urb_complete(struct urb *urb)
{
struct ub_dev *sc = urb->context;
@@ -1546,9 +1558,9 @@ static void ub_reset_enter(struct ub_dev *sc, int try)
schedule_work(&sc->reset_work);
}
-static void ub_reset_task(void *arg)
+static void ub_reset_task(struct work_struct *work)
{
- struct ub_dev *sc = arg;
+ struct ub_dev *sc = container_of(work, struct ub_dev, reset_work);
unsigned long flags;
struct list_head *p;
struct ub_lun *lun;
@@ -1911,7 +1923,7 @@ err_alloc:
/*
*/
-static void ub_probe_urb_complete(struct urb *urb, struct pt_regs *pt)
+static void ub_probe_urb_complete(struct urb *urb)
{
struct completion *cop = urb->context;
complete(cop);
@@ -2167,7 +2179,7 @@ static int ub_probe(struct usb_interface *intf,
usb_init_urb(&sc->work_urb);
tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
atomic_set(&sc->poison, 0);
- INIT_WORK(&sc->reset_work, ub_reset_task, sc);
+ INIT_WORK(&sc->reset_work, ub_reset_task);
init_waitqueue_head(&sc->reset_wait);
init_timer(&sc->work_timer);
diff --git a/drivers/block/umem.c b/drivers/block/umem.c
index 5d8925bd904..30f16bd8365 100644
--- a/drivers/block/umem.c
+++ b/drivers/block/umem.c
@@ -552,7 +552,8 @@ static void process_page(unsigned long data)
static int mm_make_request(request_queue_t *q, struct bio *bio)
{
struct cardinfo *card = q->queuedata;
- pr_debug("mm_make_request %ld %d\n", bh->b_rsector, bh->b_size);
+ pr_debug("mm_make_request %llu %u\n",
+ (unsigned long long)bio->bi_sector, bio->bi_size);
bio->bi_phys_segments = bio->bi_idx; /* count of completed segments*/
spin_lock_irq(&card->lock);
@@ -570,7 +571,7 @@ static int mm_make_request(request_queue_t *q, struct bio *bio)
-- mm_interrupt
-----------------------------------------------------------------------------------
*/
-static irqreturn_t mm_interrupt(int irq, void *__card, struct pt_regs *regs)
+static irqreturn_t mm_interrupt(int irq, void *__card)
{
struct cardinfo *card = (struct cardinfo *) __card;
unsigned int dma_status;
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index ec5a1b90a0a..e19ba4ebcd4 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -759,6 +759,8 @@ static struct vio_driver viodasd_driver = {
}
};
+static int need_delete_probe;
+
/*
* Initialize the whole device driver. Handle module and non-module
* versions
@@ -773,46 +775,67 @@ static int __init viodasd_init(void)
if (viopath_hostLp == HvLpIndexInvalid) {
printk(VIOD_KERN_WARNING "invalid hosting partition\n");
- return -EIO;
+ rc = -EIO;
+ goto early_fail;
}
printk(VIOD_KERN_INFO "vers " VIOD_VERS ", hosting partition %d\n",
viopath_hostLp);
/* register the block device */
- if (register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME)) {
+ rc = register_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
+ if (rc) {
printk(VIOD_KERN_WARNING
"Unable to get major number %d for %s\n",
VIODASD_MAJOR, VIOD_GENHD_NAME);
- return -EIO;
+ goto early_fail;
}
/* Actually open the path to the hosting partition */
- if (viopath_open(viopath_hostLp, viomajorsubtype_blockio,
- VIOMAXREQ + 2)) {
+ rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio,
+ VIOMAXREQ + 2);
+ if (rc) {
printk(VIOD_KERN_WARNING
"error opening path to host partition %d\n",
viopath_hostLp);
- unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
- return -EIO;
+ goto unregister_blk;
}
/* Initialize our request handler */
vio_setHandler(viomajorsubtype_blockio, handle_block_event);
rc = vio_register_driver(&viodasd_driver);
- if (rc == 0)
- driver_create_file(&viodasd_driver.driver, &driver_attr_probe);
+ if (rc) {
+ printk(VIOD_KERN_WARNING "vio_register_driver failed\n");
+ goto unset_handler;
+ }
+
+ /*
+ * If this call fails, it just means that we cannot dynamically
+ * add virtual disks, but the driver will still work fine for
+ * all existing disk, so ignore the failure.
+ */
+ if (!driver_create_file(&viodasd_driver.driver, &driver_attr_probe))
+ need_delete_probe = 1;
+
+ return 0;
+
+unset_handler:
+ vio_clearHandler(viomajorsubtype_blockio);
+ viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2);
+unregister_blk:
+ unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
+early_fail:
return rc;
}
module_init(viodasd_init);
-void viodasd_exit(void)
+void __exit viodasd_exit(void)
{
- driver_remove_file(&viodasd_driver.driver, &driver_attr_probe);
+ if (need_delete_probe)
+ driver_remove_file(&viodasd_driver.driver, &driver_attr_probe);
vio_unregister_driver(&viodasd_driver);
vio_clearHandler(viomajorsubtype_blockio);
- unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
viopath_close(viopath_hostLp, viomajorsubtype_blockio, VIOMAXREQ + 2);
+ unregister_blkdev(VIODASD_MAJOR, VIOD_GENHD_NAME);
}
-
module_exit(viodasd_exit);
diff --git a/drivers/block/xd.c b/drivers/block/xd.c
index e828e4cbd3e..0d97b7eb818 100644
--- a/drivers/block/xd.c
+++ b/drivers/block/xd.c
@@ -48,9 +48,9 @@
#include <linux/blkdev.h>
#include <linux/blkpg.h>
#include <linux/delay.h>
+#include <linux/io.h>
#include <asm/system.h>
-#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/dma.h>
@@ -313,7 +313,7 @@ static void do_xd_request (request_queue_t * q)
int res = 0;
int retry;
- if (!(req->flags & REQ_CMD)) {
+ if (!blk_fs_request(req)) {
end_request(req, 0);
continue;
}
@@ -462,8 +462,7 @@ static void xd_recalibrate (u_char drive)
}
/* xd_interrupt_handler: interrupt service routine */
-static irqreturn_t xd_interrupt_handler(int irq, void *dev_id,
- struct pt_regs *regs)
+static irqreturn_t xd_interrupt_handler(int irq, void *dev_id)
{
if (inb(XD_STATUS) & STAT_INTERRUPT) { /* check if it was our device */
#ifdef DEBUG_OTHER
diff --git a/drivers/block/xd.h b/drivers/block/xd.h
index 71ac2e3dffc..82e090fea95 100644
--- a/drivers/block/xd.h
+++ b/drivers/block/xd.h
@@ -109,8 +109,7 @@ static int xd_ioctl (struct inode *inode,struct file *file,unsigned int cmd,unsi
static int xd_readwrite (u_char operation,XD_INFO *disk,char *buffer,u_int block,u_int count);
static void xd_recalibrate (u_char drive);
-static irqreturn_t xd_interrupt_handler(int irq, void *dev_id,
- struct pt_regs *regs);
+static irqreturn_t xd_interrupt_handler(int irq, void *dev_id);
static u_char xd_setup_dma (u_char opcode,u_char *buffer,u_int count);
static u_char *xd_build (u_char *cmdblk,u_char command,u_char drive,u_char head,u_short cylinder,u_char sector,u_char count,u_char control);
static void xd_watchdog (unsigned long unused);
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c
index 82ddbdd7bd4..7cc2685ca84 100644
--- a/drivers/block/z2ram.c
+++ b/drivers/block/z2ram.c
@@ -329,7 +329,7 @@ static struct kobject *z2_find(dev_t dev, int *part, void *data)
static struct request_queue *z2_queue;
-int __init
+static int __init
z2_init(void)
{
int ret;
@@ -370,26 +370,7 @@ err:
return ret;
}
-#if defined(MODULE)
-
-MODULE_LICENSE("GPL");
-
-int
-init_module( void )
-{
- int error;
-
- error = z2_init();
- if ( error == 0 )
- {
- printk( KERN_INFO DEVICE_NAME ": loaded as module\n" );
- }
-
- return error;
-}
-
-void
-cleanup_module( void )
+static void __exit z2_exit(void)
{
int i, j;
blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), 256);
@@ -425,4 +406,7 @@ cleanup_module( void )
return;
}
-#endif
+
+module_init(z2_init);
+module_exit(z2_exit);
+MODULE_LICENSE("GPL");