From 3f437937577e9bfef42a9eaf980b25e6abdb38a6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Mar 2003 22:27:40 -0800 Subject: [PATCH] i2c i2c-i801.c: remove #ifdefs and fix all printk() to use dev_*(). --- drivers/i2c/busses/i2c-i801.c | 155 ++++++++++++++++-------------------------- 1 file changed, 57 insertions(+), 98 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index b1556e08ce54..a0a746409ed7 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -152,15 +152,15 @@ static int i801_setup(struct pci_dev *dev) pci_read_config_word(I801_dev, SMBBA, &i801_smba); i801_smba &= 0xfff0; if(i801_smba == 0) { - printk(KERN_ERR "i2c-i801.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + dev_err(&dev->dev, "SMB base address uninitialized" + "- upgrade BIOS or use force_addr=0xaddr\n"); return -ENODEV; } } if (check_region(i801_smba, (isich4 ? 16 : 8))) { - printk - (KERN_ERR "i2c-i801.o: I801_smb region 0x%x already in use!\n", - i801_smba); + dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n", + i801_smba); error_return = -ENODEV; goto END; } @@ -174,28 +174,23 @@ static int i801_setup(struct pci_dev *dev) pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe); pci_write_config_word(I801_dev, SMBBA, i801_smba); pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01); - printk - (KERN_WARNING "i2c-i801.o: WARNING: I801 SMBus interface set to new " - "address %04x!\n", i801_smba); + dev_warn(&dev->dev, "WARNING: I801 SMBus interface set to " + "new address %04x!\n", i801_smba); } else if ((temp & 1) == 0) { pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1); - printk(KERN_WARNING "i2c-i801.o: enabling SMBus device\n"); + dev_warn(&dev->dev, "enabling SMBus device\n"); } request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus"); -#ifdef DEBUG if (temp & 0x02) - printk - (KERN_DEBUG "i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n"); + dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n"); else - printk - (KERN_DEBUG "i2c-i801.o: I801 using PCI Interrupt for SMBus.\n"); + dev_dbg(&dev->dev, "I801 using PCI Interrupt for SMBus.\n"); pci_read_config_byte(I801_dev, SMBREV, &temp); - printk(KERN_DEBUG "i2c-i801.o: SMBREV = 0x%X\n", temp); - printk(KERN_DEBUG "i2c-i801.o: I801_smba = 0x%X\n", i801_smba); -#endif /* DEBUG */ + dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); + dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba); END: return error_return; @@ -214,30 +209,22 @@ int i801_transaction(void) int result = 0; int timeout = 0; -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " - "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); -#endif + dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x," + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); /* Make sure the SMBus host is ready to start transmitting */ /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { -#ifdef DEBUG - printk(KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n", - temp); -#endif + dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting... \n", + temp); outb_p(temp, SMBHSTSTS); if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { -#ifdef DEBUG - printk(KERN_DEBUG "i2c-i801.o: Failed! (%02x)\n", temp); -#endif + dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp); return -1; } else { -#ifdef DEBUG - printk(KERN_DEBUG "i2c-i801.o: Successfull!\n"); -#endif + dev_dbg(&I801_dev->dev, "Successfull!\n"); } } @@ -251,50 +238,38 @@ int i801_transaction(void) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { -#ifdef DEBUG - printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n"); + dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); result = -1; -#endif } if (temp & 0x10) { result = -1; -#ifdef DEBUG - printk(KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n"); -#endif + dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n"); } if (temp & 0x08) { result = -1; - printk - (KERN_ERR "i2c-i801.o: Bus collision! SMBus may be locked until next hard\n" - "reset. (sorry!)\n"); + dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked " + "until next hard reset. (sorry!)\n"); /* Clock stops and slave is stuck in mid-transmission */ } if (temp & 0x04) { result = -1; -#ifdef DEBUG - printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n"); -#endif + dev_dbg(&I801_dev->dev, "Error: no response!\n"); } if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00) outb_p(inb(SMBHSTSTS), SMBHSTSTS); if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) { -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-i801.o: Failed reset at end of transaction (%02x)\n", - temp); -#endif + dev_dbg(&I801_dev->dev, "Failed reset at end of transaction" + "(%02x)\n", temp); } -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " - "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); -#endif + dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); return result; } @@ -316,8 +291,8 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, pci_write_config_byte(I801_dev, SMBHSTCFG, hostc | SMBHSTCFG_I2C_EN); } else { - printk("i2c-i801.o: " - "I2C_SMBUS_I2C_BLOCK_READ not supported!\n"); + dev_err(&I801_dev->dev, + "I2C_SMBUS_I2C_BLOCK_READ not supported!\n"); return -1; } } @@ -349,13 +324,10 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, #endif outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-i801.o: Block (pre %d): CNT=%02x, CMD=%02x, ADD=%02x, " - "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBBLKDAT)); -#endif + dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, + inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), + inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); /* Make sure the SMBus host is ready to start transmitting */ temp = inb_p(SMBHSTSTS); @@ -369,16 +341,12 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, errmask=0x1e; } if (temp & errmask) { -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n", - temp); -#endif + dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " + "Resetting... \n", temp); outb_p(temp, SMBHSTSTS); if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) { - printk - (KERN_ERR "i2c-i801.o: Reset failed! (%02x)\n", - temp); + dev_err(&I801_dev->dev, + "Reset failed! (%02x)\n", temp); result = -1; goto END; } @@ -410,25 +378,19 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { result = -1; -#ifdef DEBUG - printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n"); -#endif + dev_dbg(&I801_dev->dev, "SMBus Timeout!\n"); } if (temp & 0x10) { result = -1; -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n"); -#endif + dev_dbg(&I801_dev->dev, + "Error: Failed bus transaction\n"); } else if (temp & 0x08) { result = -1; - printk(KERN_ERR "i2c-i801.o: Bus collision!\n"); + dev_err(&I801_dev->dev, "Bus collision!\n"); } else if (temp & 0x04) { result = -1; -#ifdef DEBUG - printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n"); -#endif + dev_dbg(&I801_dev->dev, "Error: no response!\n"); } if (i == 1 && read_write == I2C_SMBUS_READ) { @@ -448,18 +410,15 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, if ((temp & 0x9e) != 0x00) outb_p(temp, SMBHSTSTS); /* signals SMBBLKDAT ready */ -#ifdef DEBUG if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) { - printk - (KERN_DEBUG "i2c-i801.o: Bad status (%02x) at end of transaction\n", - temp); + dev_dbg(&I801_dev->dev, + "Bad status (%02x) at end of transaction\n", + temp); } - printk - (KERN_DEBUG "i2c-i801.o: Block (post %d): CNT=%02x, CMD=%02x, ADD=%02x, " - "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBBLKDAT)); -#endif + dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, BLKDAT=%02x\n", i, + inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), + inb_p(SMBHSTDAT0), inb_p(SMBBLKDAT)); if (result < 0) goto END; @@ -476,7 +435,7 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, && (timeout++ < MAX_TIMEOUT)); if (timeout >= MAX_TIMEOUT) { - printk(KERN_DEBUG "i2c-i801.o: PEC Timeout!\n"); + dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); } #if 0 /* now using HW PEC */ if(read_write == I2C_SMBUS_READ) { @@ -554,7 +513,7 @@ s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, break; case I2C_SMBUS_PROC_CALL: default: - printk(KERN_ERR "i2c-i801.o: Unsupported transaction %d\n", size); + dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size); return -1; } @@ -667,8 +626,8 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id { if (i801_setup(dev)) { - printk - (KERN_WARNING "i2c-i801.o: I801 not detected, module not inserted.\n"); + dev_warn(&dev->dev, + "I801 not detected, module not inserted.\n"); return -ENODEV; } @@ -694,7 +653,7 @@ static struct pci_driver i801_driver = { static int __init i2c_i801_init(void) { - printk(KERN_INFO "i2c-i801.o version %s (%s)\n", I2C_VERSION, I2C_DATE); + printk(KERN_INFO "i2c-i801 version %s (%s)\n", I2C_VERSION, I2C_DATE); return pci_module_init(&i801_driver); } -- cgit v1.2.3 From f8770ea0dcd44e4b763767b256c807b4b9b396da Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Mar 2003 22:36:49 -0800 Subject: [PATCH] i2c i2c-i801.c: remove check_region() usage. --- drivers/i2c/busses/i2c-i801.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index a0a746409ed7..ce4f199af4f6 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -158,10 +158,10 @@ static int i801_setup(struct pci_dev *dev) } } - if (check_region(i801_smba, (isich4 ? 16 : 8))) { + if (!request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus")) { dev_err(&dev->dev, "I801_smb region 0x%x already in use!\n", i801_smba); - error_return = -ENODEV; + error_return = -EBUSY; goto END; } @@ -181,8 +181,6 @@ static int i801_setup(struct pci_dev *dev) dev_warn(&dev->dev, "enabling SMBus device\n"); } - request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus"); - if (temp & 0x02) dev_dbg(&dev->dev, "I801 using Interrupt SMI# for SMBus.\n"); else -- cgit v1.2.3 From e6dffc04d3bc13403d15c32c286606bf7374ecb3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Mar 2003 22:37:20 -0800 Subject: [PATCH] i2c i2c-i801.c: fix up the pci id matching, and change to use proper pci ids. --- drivers/i2c/busses/i2c-i801.c | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index ce4f199af4f6..1b0ff30009b9 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -55,21 +55,6 @@ MODULE_LICENSE("GPL"); #define HAVE_PEC #endif -#ifndef PCI_DEVICE_ID_INTEL_82801CA_SMBUS -#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS 0x2483 -#endif - -#ifndef PCI_DEVICE_ID_INTEL_82801DB_SMBUS -#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS 0x24C3 -#endif - -static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3, - PCI_DEVICE_ID_INTEL_82801AB_3, - PCI_DEVICE_ID_INTEL_82801BA_2, - PCI_DEVICE_ID_INTEL_82801CA_SMBUS, - PCI_DEVICE_ID_INTEL_82801DB_SMBUS, - 0 }; - /* I801 SMBus address offsets */ #define SMBHSTSTS (0 + i801_smba) #define SMBHSTCNT (2 + i801_smba) @@ -135,7 +120,6 @@ static int isich4; static int i801_setup(struct pci_dev *dev) { int error_return = 0; - int *num = supported; unsigned char temp; /* Note: we keep on searching until we have found 'function 3' */ @@ -143,7 +127,10 @@ static int i801_setup(struct pci_dev *dev) return -ENODEV; I801_dev = dev; - isich4 = *num == PCI_DEVICE_ID_INTEL_82801DB_SMBUS; + if (dev->device == PCI_DEVICE_ID_INTEL_82801DB_3) + isich4 = 1; + else + isich4 = 0; /* Determine the address of the SMBus areas */ if (force_addr) { @@ -290,7 +277,7 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, hostc | SMBHSTCFG_I2C_EN); } else { dev_err(&I801_dev->dev, - "I2C_SMBUS_I2C_BLOCK_READ not supported!\n"); + "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); return -1; } } @@ -607,13 +594,13 @@ static struct pci_device_id i801_ids[] __devinitdata = { }, { .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801CA_SMBUS, + .device = PCI_DEVICE_ID_INTEL_82801CA_3, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, { .vendor = PCI_VENDOR_ID_INTEL, - .device = PCI_DEVICE_ID_INTEL_82801DB_SMBUS, + .device = PCI_DEVICE_ID_INTEL_82801DB_3, .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, }, -- cgit v1.2.3 From 3a1eb5cd306d56e0b0d5f3733101eaef1d4e98f8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Mar 2003 22:37:45 -0800 Subject: [PATCH] i2c i2c-i801.c: fix up formatting and whitespace issues. Also made everything static, no global functions are needed here. --- drivers/i2c/busses/i2c-i801.c | 179 ++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 101 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 1b0ff30009b9..9f70bc88e1c5 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -49,50 +49,48 @@ #include #include -MODULE_LICENSE("GPL"); - #ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC #define HAVE_PEC #endif /* I801 SMBus address offsets */ -#define SMBHSTSTS (0 + i801_smba) -#define SMBHSTCNT (2 + i801_smba) -#define SMBHSTCMD (3 + i801_smba) -#define SMBHSTADD (4 + i801_smba) -#define SMBHSTDAT0 (5 + i801_smba) -#define SMBHSTDAT1 (6 + i801_smba) -#define SMBBLKDAT (7 + i801_smba) -#define SMBPEC (8 + i801_smba) /* ICH4 only */ -#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */ -#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ +#define SMBHSTSTS (0 + i801_smba) +#define SMBHSTCNT (2 + i801_smba) +#define SMBHSTCMD (3 + i801_smba) +#define SMBHSTADD (4 + i801_smba) +#define SMBHSTDAT0 (5 + i801_smba) +#define SMBHSTDAT1 (6 + i801_smba) +#define SMBBLKDAT (7 + i801_smba) +#define SMBPEC (8 + i801_smba) /* ICH4 only */ +#define SMBAUXSTS (12 + i801_smba) /* ICH4 only */ +#define SMBAUXCTL (13 + i801_smba) /* ICH4 only */ /* PCI Address Constants */ -#define SMBBA 0x020 -#define SMBHSTCFG 0x040 -#define SMBREV 0x008 +#define SMBBA 0x020 +#define SMBHSTCFG 0x040 +#define SMBREV 0x008 /* Host configuration bits for SMBHSTCFG */ -#define SMBHSTCFG_HST_EN 1 -#define SMBHSTCFG_SMB_SMI_EN 2 -#define SMBHSTCFG_I2C_EN 4 +#define SMBHSTCFG_HST_EN 1 +#define SMBHSTCFG_SMB_SMI_EN 2 +#define SMBHSTCFG_I2C_EN 4 /* Other settings */ -#define MAX_TIMEOUT 100 -#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ +#define MAX_TIMEOUT 100 +#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ /* I801 command constants */ -#define I801_QUICK 0x00 -#define I801_BYTE 0x04 -#define I801_BYTE_DATA 0x08 -#define I801_WORD_DATA 0x0C -#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */ -#define I801_BLOCK_DATA 0x14 -#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */ -#define I801_BLOCK_LAST 0x34 -#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */ -#define I801_START 0x40 -#define I801_PEC_EN 0x80 /* ICH4 only */ +#define I801_QUICK 0x00 +#define I801_BYTE 0x04 +#define I801_BYTE_DATA 0x08 +#define I801_WORD_DATA 0x0C +#define I801_PROC_CALL 0x10 /* later chips only, unimplemented */ +#define I801_BLOCK_DATA 0x14 +#define I801_I2C_BLOCK_DATA 0x18 /* unimplemented */ +#define I801_BLOCK_LAST 0x34 +#define I801_I2C_BLOCK_LAST 0x38 /* unimplemented */ +#define I801_START 0x40 +#define I801_PEC_EN 0x80 /* ICH4 only */ /* insmod parameters */ @@ -104,10 +102,6 @@ MODULE_PARM_DESC(force_addr, "Forcibly enable the I801 at the given address. " "EXTREMELY DANGEROUS!"); - - - - static void i801_do_pause(unsigned int amount); static int i801_transaction(void); static int i801_block_transaction(union i2c_smbus_data *data, @@ -132,7 +126,7 @@ static int i801_setup(struct pci_dev *dev) else isich4 = 0; -/* Determine the address of the SMBus areas */ + /* Determine the address of the SMBus areas */ if (force_addr) { i801_smba = force_addr & 0xfff0; } else { @@ -155,8 +149,9 @@ static int i801_setup(struct pci_dev *dev) pci_read_config_byte(I801_dev, SMBHSTCFG, &temp); temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ pci_write_config_byte(I801_dev, SMBHSTCFG, temp); -/* If force_addr is set, we program the new address here. Just to make - sure, we disable the device first. */ + + /* If force_addr is set, we program the new address here. Just to make + sure, we disable the device first. */ if (force_addr) { pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe); pci_write_config_word(I801_dev, SMBBA, i801_smba); @@ -177,18 +172,18 @@ static int i801_setup(struct pci_dev *dev) dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); dev_dbg(&dev->dev, "I801_smba = 0x%X\n", i801_smba); - END: +END: return error_return; } -void i801_do_pause(unsigned int amount) +static void i801_do_pause(unsigned int amount) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(amount); } -int i801_transaction(void) +static int i801_transaction(void) { int temp; int result = 0; @@ -259,28 +254,28 @@ int i801_transaction(void) } /* All-inclusive block transaction function */ -int i801_block_transaction(union i2c_smbus_data *data, char read_write, - int command) +static int i801_block_transaction(union i2c_smbus_data *data, char read_write, + int command) { int i, len; int smbcmd; int temp; int result = 0; int timeout; - unsigned char hostc, errmask; - - if (command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (read_write == I2C_SMBUS_WRITE) { - /* set I2C_EN bit in configuration register */ - pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); - pci_write_config_byte(I801_dev, SMBHSTCFG, - hostc | SMBHSTCFG_I2C_EN); - } else { - dev_err(&I801_dev->dev, + unsigned char hostc, errmask; + + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + if (read_write == I2C_SMBUS_WRITE) { + /* set I2C_EN bit in configuration register */ + pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc); + pci_write_config_byte(I801_dev, SMBHSTCFG, + hostc | SMBHSTCFG_I2C_EN); + } else { + dev_err(&I801_dev->dev, "I2C_SMBUS_I2C_BLOCK_READ not DB!\n"); - return -1; - } - } + return -1; + } + } if (read_write == I2C_SMBUS_WRITE) { len = data->block[0]; @@ -303,10 +298,6 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, smbcmd = I801_BLOCK_LAST; else smbcmd = I801_BLOCK_DATA; -#if 0 /* now using HW PEC */ - if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) - smbcmd |= I801_PEC_EN; -#endif outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT); dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, " @@ -316,15 +307,15 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, /* Make sure the SMBus host is ready to start transmitting */ temp = inb_p(SMBHSTSTS); - if (i == 1) { - /* Erronenous conditions before transaction: - * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ - errmask=0x9f; - } else { - /* Erronenous conditions during transaction: - * Failed, Bus_Err, Dev_Err, Intr */ - errmask=0x1e; - } + if (i == 1) { + /* Erronenous conditions before transaction: + * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */ + errmask=0x9f; + } else { + /* Erronenous conditions during transaction: + * Failed, Bus_Err, Dev_Err, Intr */ + errmask=0x1e; + } if (temp & errmask) { dev_dbg(&I801_dev->dev, "SMBus busy (%02x). " "Resetting... \n", temp); @@ -336,20 +327,14 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, goto END; } if (i != 1) { - result = -1; /* if die in middle of block transaction, fail */ - goto END; - } + /* if die in middle of block transaction, fail */ + result = -1; + goto END; + } } - if (i == 1) { -#if 0 /* #ifdef HAVE_PEC (now using HW PEC) */ - if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) { - if(read_write == I2C_SMBUS_WRITE) - outb_p(data->block[len + 1], SMBPEC); - } -#endif + if (i == 1) outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT); - } /* We will always wait for a fraction of a second! */ timeout = 0; @@ -387,7 +372,7 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, data->block[0] = len; } - /* Retrieve/store value in SMBBLKDAT */ + /* Retrieve/store value in SMBBLKDAT */ if (read_write == I2C_SMBUS_READ) data->block[i] = inb_p(SMBBLKDAT); if (read_write == I2C_SMBUS_WRITE && i+1 <= len) @@ -422,27 +407,22 @@ int i801_block_transaction(union i2c_smbus_data *data, char read_write, if (timeout >= MAX_TIMEOUT) { dev_dbg(&I801_dev->dev, "PEC Timeout!\n"); } -#if 0 /* now using HW PEC */ - if(read_write == I2C_SMBUS_READ) { - data->block[len + 1] = inb_p(SMBPEC); - } -#endif outb_p(temp, SMBHSTSTS); } #endif - result = 0; + result = 0; END: - if (command == I2C_SMBUS_I2C_BLOCK_DATA) { - /* restore saved configuration register value */ + if (command == I2C_SMBUS_I2C_BLOCK_DATA) { + /* restore saved configuration register value */ pci_write_config_byte(I801_dev, SMBHSTCFG, hostc); - } + } return result; } /* Return -1 on error. */ -s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, - union i2c_smbus_data * data) +static s32 i801_access(struct i2c_adapter * adap, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data * data) { int hwpec = 0; int block = 0; @@ -544,7 +524,7 @@ s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, } -u32 i801_func(struct i2c_adapter *adapter) +static u32 i801_func(struct i2c_adapter *adapter) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | @@ -571,8 +551,6 @@ static struct i2c_adapter i801_adapter = { .algo = &smbus_algorithm, }; - - static struct pci_device_id i801_ids[] __devinitdata = { { .vendor = PCI_VENDOR_ID_INTEL, @@ -642,18 +620,17 @@ static int __init i2c_i801_init(void) return pci_module_init(&i801_driver); } - static void __exit i2c_i801_exit(void) { pci_unregister_driver(&i801_driver); release_region(i801_smba, (isich4 ? 16 : 8)); } - - -MODULE_AUTHOR - ("Frodo Looijaard , Philip Edelbrock , and Mark D. Studebaker "); +MODULE_AUTHOR ("Frodo Looijaard , " + "Philip Edelbrock , " + "and Mark D. Studebaker "); MODULE_DESCRIPTION("I801 SMBus driver"); +MODULE_LICENSE("GPL"); module_init(i2c_i801_init); module_exit(i2c_i801_exit); -- cgit v1.2.3 From ee5659391f3079a6fbbf643ad38f9df37e9b82b7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Mar 2003 01:10:51 -0800 Subject: [PATCH] i2c i2c-piix4.c: remove check_region() call. --- drivers/i2c/busses/i2c-piix4.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 5acd8211b1d6..c5f91419297e 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -149,7 +149,7 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id } } - if (check_region(piix4_smba, 8)) { + if (!request_region(piix4_smba, 8, "piix4-smbus")) { printk (KERN_ERR "i2c-piix4.o: SMB region 0x%x already in use!\n", piix4_smba); @@ -188,9 +188,6 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id } } - /* Everything is happy, let's grab the memory and set things up. */ - request_region(piix4_smba, 8, "piix4-smbus"); - #ifdef DEBUG if ((temp & 0x0E) == 8) printk -- cgit v1.2.3 From aeb7a16af6e63a5022e9d4b72fce0af29b289c28 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Mar 2003 01:12:28 -0800 Subject: [PATCH] i2c i2c-piix4: remove #ifdefs and fix all printk() to use dev_*(). --- drivers/i2c/busses/i2c-piix4.c | 118 +++++++++++++++++------------------------ 1 file changed, 48 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index c5f91419297e..d085bab18054 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -28,6 +28,8 @@ Note: we assume there can only be one device, with one SMBus interface. */ +/* #define DEBUG 1 */ + #include #include #include @@ -102,6 +104,7 @@ static int piix4_transaction(void); static unsigned short piix4_smba = 0; +static struct i2c_adapter piix4_adapter; /* * Get DMI information. @@ -125,15 +128,14 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data) return -ENODEV; - printk(KERN_INFO "i2c-piix4.o: Found %s device\n", PIIX4_dev->dev.name); + dev_info(&PIIX4_dev->dev, "Found %s device\n", PIIX4_dev->dev.name); if(ibm_dmi_probe()) { - printk - (KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n"); - printk - (KERN_ERR " your serial eeprom! Refusing to load module!\n"); - error_return = -EPERM; - goto END; + dev_err(&PIIX4_dev->dev, "IBM Laptop detected; this module " + "may corrupt your serial eeprom! Refusing to load " + "module!\n"); + error_return = -EPERM; + goto END; } /* Determine the address of the SMBus areas */ @@ -144,15 +146,16 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba); piix4_smba &= 0xfff0; if(piix4_smba == 0) { - printk(KERN_ERR "i2c-piix4.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + dev_err(&PIIX4_dev->dev, "SMB base address " + "uninitialized - upgrade BIOS or use " + "force_addr=0xaddr\n"); return -ENODEV; } } if (!request_region(piix4_smba, 8, "piix4-smbus")) { - printk - (KERN_ERR "i2c-piix4.o: SMB region 0x%x already in use!\n", - piix4_smba); + dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n", + piix4_smba); error_return = -ENODEV; goto END; } @@ -164,9 +167,8 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe); pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba); pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01); - printk - (KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to new " - "address %04x!\n", piix4_smba); + dev_info(&PIIX4_dev->dev, "WARNING: SMBus interface set to " + "new address %04x!\n", piix4_smba); } else if ((temp & 1) == 0) { if (force) { /* This should never need to be done, but has been noted that @@ -177,33 +179,28 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id resorting to this. */ pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 1); - printk - (KERN_NOTICE "i2c-piix4.o: WARNING: SMBus interface has been FORCEFULLY " - "ENABLED!\n"); + dev_printk(KERN_NOTICE, &PIIX4_dev->dev, + "WARNING: SMBus interface has been " + "FORCEFULLY ENABLED!\n"); } else { - printk - (KERN_ERR "i2c-piix4.o: Host SMBus controller not enabled!\n"); + dev_err(&PIIX4_dev->dev, + "Host SMBus controller not enabled!\n"); error_return = -ENODEV; goto END; } } -#ifdef DEBUG if ((temp & 0x0E) == 8) - printk - (KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n"); else if ((temp & 0x0E) == 0) - printk - (KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# for SMBus.\n"); + dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n"); else - printk - (KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration (or code out " - "of date)!\n"); + dev_err(&PIIX4_dev->dev, "Illegal Interrupt configuration " + "(or code out of date)!\n"); pci_read_config_byte(PIIX4_dev, SMBREV, &temp); - printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp); - printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba); -#endif /* DEBUG */ + dev_dbg(&PIIX4_dev->dev, "SMBREV = 0x%X\n", temp); + dev_dbg(&PIIX4_dev->dev, "SMBA = 0x%X\n", piix4_smba); END: return error_return; @@ -224,29 +221,21 @@ static int piix4_transaction(void) int result = 0; int timeout = 0; -#ifdef DEBUG - printk - (KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " - "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); -#endif + dev_dbg(&piix4_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); /* Make sure the SMBus host is ready to start transmitting */ if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting... \n", - temp); -#endif + dev_dbg(&piix4_adapter.dev, "SMBus busy (%02x). " + "Resetting... \n", temp); outb_p(temp, SMBHSTSTS); if ((temp = inb_p(SMBHSTSTS)) != 0x00) { -#ifdef DEBUG - printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp); -#endif + dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp); return -1; } else { -#ifdef DEBUG - printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n"); -#endif + dev_dbg(&piix4_adapter.dev, "Successfull!\n"); } } @@ -259,50 +248,40 @@ static int piix4_transaction(void) temp = inb_p(SMBHSTSTS); } while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT)); -#ifdef DEBUG /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { - printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n"); + dev_err(&piix4_adapter.dev, "SMBus Timeout!\n"); result = -1; } -#endif if (temp & 0x10) { result = -1; -#ifdef DEBUG - printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n"); -#endif + dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n"); } if (temp & 0x08) { result = -1; - printk - (KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n" - "reset. (sorry!)\n"); + dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be " + "locked until next hard reset. (sorry!)\n"); /* Clock stops and slave is stuck in mid-transmission */ } if (temp & 0x04) { result = -1; -#ifdef DEBUG - printk(KERN_ERR "i2c-piix4.o: Error: no response!\n"); -#endif + dev_err(&piix4_adapter.dev, "Error: no response!\n"); } if (inb_p(SMBHSTSTS) != 0x00) outb_p(inb(SMBHSTSTS), SMBHSTSTS); -#ifdef DEBUG if ((temp = inb_p(SMBHSTSTS)) != 0x00) { - printk - (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n", - temp); + dev_err(&piix4_adapter.dev, "Failed reset at end of " + "transaction (%02x)\n", temp); } - printk - (KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, " - "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); -#endif + dev_dbg(&piix4_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), + inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), + inb_p(SMBHSTDAT1)); return result; } @@ -315,8 +294,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, switch (size) { case I2C_SMBUS_PROC_CALL: - printk - (KERN_ERR "i2c-piix4.o: I2C_SMBUS_PROC_CALL not supported!\n"); + dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); return -1; case I2C_SMBUS_QUICK: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), @@ -496,7 +474,7 @@ static struct pci_driver piix4_driver = { static int __init i2c_piix4_init(void) { - printk("i2c-piix4.o version %s (%s)\n", I2C_VERSION, I2C_DATE); + printk(KERN_INFO "i2c-piix4 version %s (%s)\n", I2C_VERSION, I2C_DATE); return pci_module_init(&piix4_driver); } -- cgit v1.2.3 From 0058c17beaa1a3752a6703e3f824fd8354a6150e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Mar 2003 01:13:06 -0800 Subject: [PATCH] i2c i2c-piix4.c: fix up formatting and whitespace issues. --- drivers/i2c/busses/i2c-piix4.c | 80 ++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index d085bab18054..a1048f7b5cbe 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -51,37 +51,37 @@ struct sd { }; /* PIIX4 SMBus address offsets */ -#define SMBHSTSTS (0 + piix4_smba) -#define SMBHSLVSTS (1 + piix4_smba) -#define SMBHSTCNT (2 + piix4_smba) -#define SMBHSTCMD (3 + piix4_smba) -#define SMBHSTADD (4 + piix4_smba) -#define SMBHSTDAT0 (5 + piix4_smba) -#define SMBHSTDAT1 (6 + piix4_smba) -#define SMBBLKDAT (7 + piix4_smba) -#define SMBSLVCNT (8 + piix4_smba) -#define SMBSHDWCMD (9 + piix4_smba) -#define SMBSLVEVT (0xA + piix4_smba) -#define SMBSLVDAT (0xC + piix4_smba) +#define SMBHSTSTS (0 + piix4_smba) +#define SMBHSLVSTS (1 + piix4_smba) +#define SMBHSTCNT (2 + piix4_smba) +#define SMBHSTCMD (3 + piix4_smba) +#define SMBHSTADD (4 + piix4_smba) +#define SMBHSTDAT0 (5 + piix4_smba) +#define SMBHSTDAT1 (6 + piix4_smba) +#define SMBBLKDAT (7 + piix4_smba) +#define SMBSLVCNT (8 + piix4_smba) +#define SMBSHDWCMD (9 + piix4_smba) +#define SMBSLVEVT (0xA + piix4_smba) +#define SMBSLVDAT (0xC + piix4_smba) /* PCI Address Constants */ -#define SMBBA 0x090 -#define SMBHSTCFG 0x0D2 -#define SMBSLVC 0x0D3 -#define SMBSHDW1 0x0D4 -#define SMBSHDW2 0x0D5 -#define SMBREV 0x0D6 +#define SMBBA 0x090 +#define SMBHSTCFG 0x0D2 +#define SMBSLVC 0x0D3 +#define SMBSHDW1 0x0D4 +#define SMBSHDW2 0x0D5 +#define SMBREV 0x0D6 /* Other settings */ -#define MAX_TIMEOUT 500 -#define ENABLE_INT9 0 +#define MAX_TIMEOUT 500 +#define ENABLE_INT9 0 /* PIIX4 constants */ -#define PIIX4_QUICK 0x00 -#define PIIX4_BYTE 0x04 -#define PIIX4_BYTE_DATA 0x08 -#define PIIX4_WORD_DATA 0x0C -#define PIIX4_BLOCK_DATA 0x14 +#define PIIX4_QUICK 0x00 +#define PIIX4_BYTE 0x04 +#define PIIX4_BYTE_DATA 0x08 +#define PIIX4_WORD_DATA 0x0C +#define PIIX4_BLOCK_DATA 0x14 /* insmod parameters */ @@ -138,7 +138,7 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id goto END; } -/* Determine the address of the SMBus areas */ + /* Determine the address of the SMBus areas */ if (force_addr) { piix4_smba = force_addr & 0xfff0; force = 0; @@ -161,8 +161,8 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id } pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); -/* If force_addr is set, we program the new address here. Just to make - sure, we disable the PIIX4 first. */ + /* If force_addr is set, we program the new address here. Just to make + sure, we disable the PIIX4 first. */ if (force_addr) { pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe); pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba); @@ -171,12 +171,14 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id "new address %04x!\n", piix4_smba); } else if ((temp & 1) == 0) { if (force) { -/* This should never need to be done, but has been noted that - many Dell machines have the SMBus interface on the PIIX4 - disabled!? NOTE: This assumes I/O space and other allocations WERE - done by the Bios! Don't complain if your hardware does weird - things after enabling this. :') Check for Bios updates before - resorting to this. */ + /* This should never need to be done, but has been + * noted that many Dell machines have the SMBus + * interface on the PIIX4 disabled!? NOTE: This assumes + * I/O space and other allocations WERE done by the + * Bios! Don't complain if your hardware does weird + * things after enabling this. :') Check for Bios + * updates before resorting to this. + */ pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 1); dev_printk(KERN_NOTICE, &PIIX4_dev->dev, @@ -202,11 +204,10 @@ static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id dev_dbg(&PIIX4_dev->dev, "SMBREV = 0x%X\n", temp); dev_dbg(&PIIX4_dev->dev, "SMBA = 0x%X\n", piix4_smba); - END: +END: return error_return; } - /* Internally used pause function */ static void piix4_do_pause(unsigned int amount) { @@ -377,7 +378,6 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, return 0; } - static u32 piix4_func(struct i2c_adapter *adapter) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | @@ -399,8 +399,6 @@ static struct i2c_adapter piix4_adapter = { .algo = &smbus_algorithm, }; - - static struct pci_device_id piix4_ids[] __devinitdata = { { .vendor = PCI_VENDOR_ID_INTEL, @@ -443,7 +441,7 @@ static struct pci_device_id piix4_ids[] __devinitdata = { static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) { int retval; - + retval = piix4_setup(dev, id); if (retval) return retval; @@ -485,8 +483,6 @@ static void __exit i2c_piix4_exit(void) release_region(piix4_smba, 8); } - - MODULE_AUTHOR ("Frodo Looijaard and Philip Edelbrock "); MODULE_DESCRIPTION("PIIX4 SMBus driver"); -- cgit v1.2.3 From fce83260a9b263b28c5d028f3962a429d0bd0726 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 18 Mar 2003 01:46:05 -0800 Subject: [FB ATY]: CONFIG_FB_ATY needs cfbcopyarea.o --- drivers/video/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 227bd6af7e85..610efa8be652 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -58,7 +58,7 @@ obj-$(CONFIG_FB_TX3912) += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbi obj-$(CONFIG_FB_MATROX) += matrox/ obj-$(CONFIG_FB_RIVA) += riva/ cfbimgblt.o vgastate.o obj-$(CONFIG_FB_SIS) += sis/ -obj-$(CONFIG_FB_ATY) += aty/ cfbimgblt.o cfbfillrect.o cfbimgblt.o +obj-$(CONFIG_FB_ATY) += aty/ cfbimgblt.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_I810) += i810/ cfbfillrect.o cfbcopyarea.o \ cfbimgblt.o vgastate.o -- cgit v1.2.3 From 647bcb6e12efddf74d1024b24a4a3b90b3fc85e9 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 18 Mar 2003 19:21:52 -0800 Subject: [PATCH] USB: fix to synchronous API regarding memory allocation some part of the synchronous API is used in the block io error handling code paths. Therefore it may use only GFP_NOIO, not GFP_KERNEL. - avoid deadlock due to wrong memory allocation in block io path --- drivers/usb/core/message.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 97c986e346d2..793a82b23ac2 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -88,7 +88,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, int retv; int length; - urb = usb_alloc_urb(0, GFP_KERNEL); + urb = usb_alloc_urb(0, GFP_NOIO); if (!urb) return -ENOMEM; @@ -131,7 +131,7 @@ int usb_internal_control_msg(struct usb_device *usb_dev, unsigned int pipe, int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout) { - struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); + struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_NOIO); int ret; if (!dr) -- cgit v1.2.3 From d692b939f764ccd7d8290887ef1d90b2df223b01 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Tue, 18 Mar 2003 19:22:14 -0800 Subject: [PATCH] USB speedtouch: cosmetic comment changes --- drivers/usb/misc/speedtouch.c | 53 ++++++++++++------------------------------- 1 file changed, 14 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/speedtouch.c b/drivers/usb/misc/speedtouch.c index 58bb47c64e6a..d474877b03c0 100644 --- a/drivers/usb/misc/speedtouch.c +++ b/drivers/usb/misc/speedtouch.c @@ -690,15 +690,9 @@ static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb) } -/************ -** ATM ** -************/ - -/*************************************************************************** -* -* init functions -* -****************************************************************************/ +/********** +** ATM ** +**********/ static void udsl_atm_dev_close (struct atm_dev *dev) { @@ -718,13 +712,6 @@ static void udsl_atm_dev_close (struct atm_dev *dev) dev->dev_data = NULL; } - -/*************************************************************************** -* -* ATM helper functions -* -****************************************************************************/ - static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page) { struct udsl_instance_data *instance = atm_dev->dev_data; @@ -778,13 +765,6 @@ static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page) return 0; } - -/*************************************************************************** -* -* SAR driver entries -* -****************************************************************************/ - static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci) { struct udsl_instance_data *instance = vcc->dev->dev_data; @@ -866,9 +846,9 @@ static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg) } -/************ -** USB ** -************/ +/********** +** USB ** +**********/ static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *user_data) { @@ -1180,11 +1160,9 @@ static void udsl_usb_disconnect (struct usb_interface *intf) } -/*************************************************************************** -* -* Driver Init -* -****************************************************************************/ +/*********** +** init ** +***********/ static int __init udsl_usb_init (void) { @@ -1215,13 +1193,11 @@ MODULE_DESCRIPTION (DRIVER_DESC); MODULE_LICENSE ("GPL"); -#ifdef DEBUG_PACKET -/******************************************************************************* -* -* Debug -* -*******************************************************************************/ +/************ +** debug ** +************/ +#ifdef DEBUG_PACKET static int udsl_print_packet (const unsigned char *data, int len) { unsigned char buffer [256]; @@ -1237,5 +1213,4 @@ static int udsl_print_packet (const unsigned char *data, int len) } return i; } - -#endif /* PACKETDEBUG */ +#endif -- cgit v1.2.3 From cda9846c1628240d4768d4cf8f149c549f57a58d Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Tue, 18 Mar 2003 19:23:08 -0800 Subject: [PATCH] USB speedtouch: get rid of atmsar There are really only two patches: add atmsar stuff into speedtouch.c; and update the Makefile. The other changes are: delete atmsar.c and atmsar.h, rename speedtouch.c to speedtch.c. --- drivers/usb/misc/Makefile | 2 - drivers/usb/misc/atmsar.c | 380 ----------- drivers/usb/misc/atmsar.h | 87 --- drivers/usb/misc/speedtch.c | 1514 +++++++++++++++++++++++++++++++++++++++++ drivers/usb/misc/speedtouch.c | 1216 --------------------------------- 5 files changed, 1514 insertions(+), 1685 deletions(-) delete mode 100644 drivers/usb/misc/atmsar.c delete mode 100644 drivers/usb/misc/atmsar.h create mode 100644 drivers/usb/misc/speedtch.c delete mode 100644 drivers/usb/misc/speedtouch.c (limited to 'drivers') diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index e333dbe6d07b..c24cebd97cba 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -12,5 +12,3 @@ obj-$(CONFIG_USB_SPEEDTOUCH) += speedtch.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TIGL) += tiglusb.o obj-$(CONFIG_USB_USS720) += uss720.o - -speedtch-objs := speedtouch.o atmsar.o diff --git a/drivers/usb/misc/atmsar.c b/drivers/usb/misc/atmsar.c deleted file mode 100644 index e9afd62768c8..000000000000 --- a/drivers/usb/misc/atmsar.c +++ /dev/null @@ -1,380 +0,0 @@ -/****************************************************************************** - * atmsar.c -- General SAR library for ATM devices. - * - * Copyright (C) 2000, Johan Verrept - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - ******************************************************************************/ - -/* - * Written by Johan Verrept (Johan.Verrept@advalvas.be) - * - * 0.2.4A: - Version for inclusion in 2.5 series kernel - * - Modifications by Richard Purdie (rpurdie@rpsys.net) - * - replaced "sarlib" with "atmsar" - * - adaptations for inclusion in kernel tree - * - * 0.2.4: - Fixed wrong buffer overrun check in atmsar_decode_rawcell() - * reported by Stephen Robinson - * - Fixed bug when input skb did not contain a multple of 52/53 - * bytes (would happen when the speedtouch device resynced) - * also reported by Stephen Robinson - * - * 0.2.3: - Fixed wrong allocation size. caused memory corruption in some - * cases. Reported by Vladimir Dergachev - * - Added some comments - * - * 0.2.2: - Fixed CRCASM - * patch from Linus Flannagan - * - Fixed problem when user did NOT use the - * ATMSAR_USE_53BYTE_CELL flag. - * reported by Piers Scannell - * - No more in-buffer rewriting for cloned buffers. - * - Removed the PII specific CFLAGS in the Makefile. - * - * 0.2.1: - removed dependency on alloc_tx. tis presented problems when - * using this with the br2684 code. - * - * 0.2: - added AAL0 reassembly - * - added alloc_tx support - * - replaced alloc_skb in decode functions to dev_alloc_skb to - * allow calling from interrupt - * - fixed embarassing AAL5 bug. I was setting the pti bit in the - * wrong byte... - * - fixed another emabrassing bug.. picked up the wrong crc type - * and forgot to invert the crc result... - * - fixed AAL5 length calculations. - * - removed automatic skb freeing from encode functions. - * This caused problems because i did kfree_skb it, while it - * needed to be popped. I cannot determine though whether it - * needs to be popped or not. Figu'e it out ye'self ;-) - * - added mru field. This is the buffersize. atmsar_decode_aal0 - * will use when it allocates a receive buffer. A stop gap for - * real buffer management. - * - * 0.1: - library created. - * - only contains AAL5, AAL0 can be easily added. (actually, only - * AAL0 reassembly is missing) - * - */ - -#include -#include "atmsar.h" - -/*********************** - ** - ** things to remember - ** - ***********************/ - -/* - 1. the atmsar_vcc_data list pointer MUST be initialized to NULL - 2. atmsar_encode_rawcell will drop incomplete cells. - 3. ownership of the skb goes to the library ! -*/ - -#define ATM_HDR_VPVC_MASK (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK) - -/*********************** - ** - ** LOCAL STRUCTURES - ** - ***********************/ - -/*********************** - ** - ** LOCAL MACROS - ** - ***********************/ -/* -#define DEBUG 1 -*/ -#ifdef DEBUG -#define PDEBUG(arg...) printk(KERN_DEBUG "atmsar: " arg) -#else -#define PDEBUG(arg...) -#endif - -#define ADD_HEADER(dest, header) \ - *dest++ = (unsigned char) (header >> 24); \ - *dest++ = (unsigned char) (header >> 16); \ - *dest++ = (unsigned char) (header >> 8); \ - *dest++ = (unsigned char) (header & 0xff); - - -struct atmsar_vcc_data *atmsar_open (struct atmsar_vcc_data **list, struct atm_vcc *vcc, uint type, - ushort vpi, ushort vci, unchar pti, unchar gfc, uint flags) -{ - struct atmsar_vcc_data *new; - - if (!vcc) - return NULL; - - new = kmalloc (sizeof (struct atmsar_vcc_data), GFP_KERNEL); - - if (!new) - return NULL; - - memset (new, 0, sizeof (struct atmsar_vcc_data)); - new->vcc = vcc; - new->stats = vcc->stats; - new->type = type; - new->next = NULL; - new->gfc = gfc; - new->vp = vpi; - new->vc = vci; - new->pti = pti; - - switch (type) { - case ATMSAR_TYPE_AAL0: - new->mtu = ATMSAR_DEF_MTU_AAL0; - break; - case ATMSAR_TYPE_AAL1: - new->mtu = ATMSAR_DEF_MTU_AAL1; - break; - case ATMSAR_TYPE_AAL2: - new->mtu = ATMSAR_DEF_MTU_AAL2; - break; - case ATMSAR_TYPE_AAL34: - /* not supported */ - new->mtu = ATMSAR_DEF_MTU_AAL34; - break; - case ATMSAR_TYPE_AAL5: - new->mtu = ATMSAR_DEF_MTU_AAL5; - break; - } - - new->atmHeader = ((unsigned long) gfc << ATM_HDR_GFC_SHIFT) - | ((unsigned long) vpi << ATM_HDR_VPI_SHIFT) - | ((unsigned long) vci << ATM_HDR_VCI_SHIFT) - | ((unsigned long) pti << ATM_HDR_PTI_SHIFT); - new->flags = flags; - new->next = NULL; - new->reasBuffer = NULL; - - new->next = *list; - *list = new; - - PDEBUG ("Allocated new SARLib vcc 0x%p with vp %d vc %d\n", new, vpi, vci); - - return new; -} - -void atmsar_close (struct atmsar_vcc_data **list, struct atmsar_vcc_data *vcc) -{ - struct atmsar_vcc_data *work; - - if (*list == vcc) { - *list = (*list)->next; - } else { - for (work = *list; work && work->next && (work->next != vcc); work = work->next); - - /* return if not found */ - if (work->next != vcc) - return; - - work->next = work->next->next; - } - - if (vcc->reasBuffer) { - dev_kfree_skb (vcc->reasBuffer); - } - - PDEBUG ("Allocated SARLib vcc 0x%p with vp %d vc %d\n", vcc, vcc->vp, vcc->vc); - - kfree (vcc); -} - - -/*********************** - ** - ** DECODE FUNCTIONS - ** - ***********************/ - -struct sk_buff *atmsar_decode_rawcell (struct atmsar_vcc_data *list, struct sk_buff *skb, - struct atmsar_vcc_data **ctx) -{ - while (skb->len) { - unsigned char *cell = skb->data; - unsigned char *cell_payload; - struct atmsar_vcc_data *vcc = list; - unsigned long atmHeader = - ((unsigned long) (cell[0]) << 24) | ((unsigned long) (cell[1]) << 16) | - ((unsigned long) (cell[2]) << 8) | (cell[3] & 0xff); - - PDEBUG ("atmsar_decode_rawcell (0x%p, 0x%p, 0x%p) called\n", list, skb, ctx); - PDEBUG ("atmsar_decode_rawcell skb->data %p, skb->tail %p\n", skb->data, skb->tail); - - if (!list || !skb || !ctx) - return NULL; - if (!skb->data || !skb->tail) - return NULL; - - /* here should the header CRC check be... */ - - /* look up correct vcc */ - for (; - vcc - && ((vcc->atmHeader & ATM_HDR_VPVC_MASK) != (atmHeader & ATM_HDR_VPVC_MASK)); - vcc = vcc->next); - - PDEBUG ("atmsar_decode_rawcell found vcc %p for packet on vp %d, vc %d\n", vcc, - (int) ((atmHeader & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT), - (int) ((atmHeader & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT)); - - if (vcc && (skb->len >= (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52))) { - cell_payload = cell + (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 5 : 4); - - switch (vcc->type) { - case ATMSAR_TYPE_AAL0: - /* case ATMSAR_TYPE_AAL1: when we have a decode AAL1 function... */ - { - struct sk_buff *tmp = dev_alloc_skb (vcc->mtu); - - if (tmp) { - memcpy (tmp->tail, cell_payload, 48); - skb_put (tmp, 48); - - if (vcc->stats) - atomic_inc (&vcc->stats->rx); - - skb_pull (skb, - (vcc-> - flags & ATMSAR_USE_53BYTE_CELL ? 53 : - 52)); - PDEBUG - ("atmsar_decode_rawcell returns ATMSAR_TYPE_AAL0 pdu 0x%p with length %d\n", - tmp, tmp->len); - return tmp; - }; - } - break; - case ATMSAR_TYPE_AAL1: - case ATMSAR_TYPE_AAL2: - case ATMSAR_TYPE_AAL34: - /* not supported */ - break; - case ATMSAR_TYPE_AAL5: - if (!vcc->reasBuffer) - vcc->reasBuffer = dev_alloc_skb (vcc->mtu); - - /* if alloc fails, we just drop the cell. it is possible that we can still - * receive cells on other vcc's - */ - if (vcc->reasBuffer) { - /* if (buffer overrun) discard received cells until now */ - if ((vcc->reasBuffer->len) > (vcc->mtu - 48)) - skb_trim (vcc->reasBuffer, 0); - - /* copy data */ - memcpy (vcc->reasBuffer->tail, cell_payload, 48); - skb_put (vcc->reasBuffer, 48); - - /* check for end of buffer */ - if (cell[3] & 0x2) { - struct sk_buff *tmp; - - /* the aal5 buffer ends here, cut the buffer. */ - /* buffer will always have at least one whole cell, so */ - /* don't need to check return from skb_pull */ - skb_pull (skb, - (vcc-> - flags & ATMSAR_USE_53BYTE_CELL ? 53 : - 52)); - *ctx = vcc; - tmp = vcc->reasBuffer; - vcc->reasBuffer = NULL; - - PDEBUG - ("atmsar_decode_rawcell returns ATMSAR_TYPE_AAL5 pdu 0x%p with length %d\n", - tmp, tmp->len); - return tmp; - } - } - break; - }; - /* flush the cell */ - /* buffer will always contain at least one whole cell, so don't */ - /* need to check return value from skb_pull */ - skb_pull (skb, (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52)); - } else { - /* If data is corrupt and skb doesn't hold a whole cell, flush the lot */ - if (skb_pull (skb, (list->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52)) == - NULL) - return NULL; - } - } - - return NULL; -}; - -struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff *skb) -{ - uint crc = 0xffffffff; - uint length, pdu_crc, pdu_length; - - PDEBUG ("atmsar_decode_aal5 (0x%p, 0x%p) called\n", ctx, skb); - - if (skb->len && (skb->len % 48)) - return NULL; - - length = (skb->tail[-6] << 8) + skb->tail[-5]; - pdu_crc = - (skb->tail[-4] << 24) + (skb->tail[-3] << 16) + (skb->tail[-2] << 8) + skb->tail[-1]; - pdu_length = ((length + 47 + 8) / 48) * 48; - - PDEBUG ("atmsar_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d\n", - skb->len, length, pdu_crc, pdu_length); - - /* is skb long enough ? */ - if (skb->len < pdu_length) { - if (ctx->stats) - atomic_inc (&ctx->stats->rx_err); - return NULL; - } - - /* is skb too long ? */ - if (skb->len > pdu_length) { - PDEBUG ("atmsar_decode_aal5: Warning: readjusting illeagl size %d -> %d\n", - skb->len, pdu_length); - /* buffer is too long. we can try to recover - * if we discard the first part of the skb. - * the crc will decide whether this was ok - */ - skb_pull (skb, skb->len - pdu_length); - } - - crc = ~crc32_be (crc, skb->data, pdu_length - 4); - - /* check crc */ - if (pdu_crc != crc) { - PDEBUG ("atmsar_decode_aal5: crc check failed!\n"); - if (ctx->stats) - atomic_inc (&ctx->stats->rx_err); - return NULL; - } - - /* pdu is ok */ - skb_trim (skb, length); - - /* update stats */ - if (ctx->stats) - atomic_inc (&ctx->stats->rx); - - PDEBUG ("atmsar_decode_aal5 returns pdu 0x%p with length %d\n", skb, skb->len); - return skb; -}; diff --git a/drivers/usb/misc/atmsar.h b/drivers/usb/misc/atmsar.h deleted file mode 100644 index 29727e784b72..000000000000 --- a/drivers/usb/misc/atmsar.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef _ATMSAR_H_ -#define _ATMSAR_H_ - -/****************************************************************************** - * atmsar.h -- General SAR library for ATM devices. - * - * Copyright (C) 2000, Johan Verrept - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - ******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include - -#define ATMSAR_USE_53BYTE_CELL 0x1L -#define ATMSAR_SET_PTI 0x2L - -#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) - -/* types */ -#define ATMSAR_TYPE_AAL0 ATM_AAL0 -#define ATMSAR_TYPE_AAL1 ATM_AAL1 -#define ATMSAR_TYPE_AAL2 ATM_AAL2 -#define ATMSAR_TYPE_AAL34 ATM_AAL34 -#define ATMSAR_TYPE_AAL5 ATM_AAL5 - - -/* default MTU's */ -#define ATMSAR_DEF_MTU_AAL0 48 -#define ATMSAR_DEF_MTU_AAL1 47 -#define ATMSAR_DEF_MTU_AAL2 0 /* not supported */ -#define ATMSAR_DEF_MTU_AAL34 0 /* not supported */ -#define ATMSAR_DEF_MTU_AAL5 65535 /* max mtu .. */ - -struct atmsar_vcc_data { - struct atmsar_vcc_data *next; - - /* general atmsar flags, per connection */ - int flags; - int type; - - /* connection specific non-atmsar data */ - struct atm_vcc *vcc; - struct k_atm_aal_stats *stats; - unsigned short mtu; /* max is actually 65k for AAL5... */ - - /* cell data */ - unsigned int vp; - unsigned int vc; - unsigned char gfc; - unsigned char pti; - unsigned int headerFlags; - unsigned long atmHeader; - - /* raw cell reassembly */ - struct sk_buff *reasBuffer; -}; - - -extern struct atmsar_vcc_data *atmsar_open (struct atmsar_vcc_data **list, struct atm_vcc *vcc, - uint type, ushort vpi, ushort vci, unchar pti, - unchar gfc, uint flags); -extern void atmsar_close (struct atmsar_vcc_data **list, struct atmsar_vcc_data *vcc); - -struct sk_buff *atmsar_decode_rawcell (struct atmsar_vcc_data *list, struct sk_buff *skb, - struct atmsar_vcc_data **ctx); -struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff *skb); - -#endif /* _ATMSAR_H_ */ diff --git a/drivers/usb/misc/speedtch.c b/drivers/usb/misc/speedtch.c new file mode 100644 index 000000000000..d2006a09c36e --- /dev/null +++ b/drivers/usb/misc/speedtch.c @@ -0,0 +1,1514 @@ +/****************************************************************************** + * speedtouch.c -- Alcatel SpeedTouch USB xDSL modem driver. + * + * Copyright (C) 2001, Alcatel + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + ******************************************************************************/ + +/* + * Written by Johan Verrept (Johan.Verrept@advalvas.be) + * + * 1.5A: - Version for inclusion in 2.5 series kernel + * - Modifications by Richard Purdie (rpurdie@rpsys.net) + * - made compatible with kernel 2.5.6 onwards by changing + * udsl_usb_send_data_context->urb to a pointer and adding code + * to alloc and free it + * - remove_wait_queue() added to udsl_atm_processqueue_thread() + * + * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL. + * (reported by stephen.robinson@zen.co.uk) + * + * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave() + * - unlink all active send urbs of a vcc that is being closed. + * + * 1.3.1: - added the version number + * + * 1.3: - Added multiple send urb support + * - fixed memory leak and vcc->tx_inuse starvation bug + * when not enough memory left in vcc. + * + * 1.2: - Fixed race condition in udsl_usb_send_data() + * 1.1: - Turned off packet debugging + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +#define DEBUG 1 +#define DEBUG_PACKET 1 +*/ + +#include + + +#ifdef DEBUG_PACKET +static int udsl_print_packet (const unsigned char *data, int len); +#define PACKETDEBUG(arg...) udsl_print_packet (arg) +#else +#define PACKETDEBUG(arg...) +#endif + +#define DRIVER_AUTHOR "Johan Verrept, Johan.Verrept@advalvas.be" +#define DRIVER_DESC "Driver for the Alcatel SpeedTouch USB ADSL modem" +#define DRIVER_VERSION "1.5A" + +#define SPEEDTOUCH_VENDORID 0x06b9 +#define SPEEDTOUCH_PRODUCTID 0x4061 + +#define UDSL_NUMBER_RCV_URBS 1 +#define UDSL_NUMBER_SND_URBS 1 +#define UDSL_NUMBER_SND_BUFS (2*UDSL_NUMBER_SND_URBS) +#define UDSL_RCV_BUFFER_SIZE (1*64) /* ATM cells */ +#define UDSL_SND_BUFFER_SIZE (1*64) /* ATM cells */ +/* max should be (1500 IP mtu + 2 ppp bytes + 32 * 5 cellheader overhead) for + * PPPoA and (1500 + 14 + 32*5 cellheader overhead) for PPPoE */ +#define UDSL_MAX_AAL5_MRU 2048 + +#define UDSL_IOCTL_START 1 +#define UDSL_IOCTL_STOP 2 + +/* endpoint declarations */ + +#define UDSL_ENDPOINT_DATA_OUT 0x07 +#define UDSL_ENDPOINT_DATA_IN 0x87 + +#define ATM_CELL_HEADER (ATM_CELL_SIZE - ATM_CELL_PAYLOAD) + +#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) ) + +/* usb_device_id struct */ + +static struct usb_device_id udsl_usb_ids [] = { + { USB_DEVICE (SPEEDTOUCH_VENDORID, SPEEDTOUCH_PRODUCTID) }, + { } /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE (usb, udsl_usb_ids); + +/* context declarations */ + +struct udsl_receiver { + struct list_head list; + struct sk_buff *skb; + struct urb *urb; + struct udsl_instance_data *instance; +}; + +struct udsl_send_buffer { + struct list_head list; + unsigned char *base; + unsigned char *free_start; + unsigned int free_cells; +}; + +struct udsl_sender { + struct list_head list; + struct udsl_send_buffer *buffer; + struct urb *urb; + struct udsl_instance_data *instance; +}; + +struct udsl_control { + struct atm_skb_data atm_data; + unsigned int num_cells; + unsigned int num_entire; + unsigned char cell_header [ATM_CELL_HEADER]; + unsigned int pdu_padding; + unsigned char aal5_trailer [ATM_AAL5_TRAILER]; +}; + +#define UDSL_SKB(x) ((struct udsl_control *)(x)->cb) + +struct atmsar_vcc_data { + struct atmsar_vcc_data *next; + + /* general atmsar flags, per connection */ + int flags; + int type; + + /* connection specific non-atmsar data */ + struct atm_vcc *vcc; + struct k_atm_aal_stats *stats; + unsigned short mtu; /* max is actually 65k for AAL5... */ + + /* cell data */ + unsigned int vp; + unsigned int vc; + unsigned char gfc; + unsigned char pti; + unsigned int headerFlags; + unsigned long atmHeader; + + /* raw cell reassembly */ + struct sk_buff *reasBuffer; +}; + +/* + * UDSL main driver data + */ + +struct udsl_instance_data { + struct semaphore serialize; + + /* usb device part */ + struct usb_device *usb_dev; + char description [64]; + int firmware_loaded; + + /* atm device part */ + struct atm_dev *atm_dev; + struct atmsar_vcc_data *atmsar_vcc_list; + + /* receiving */ + struct udsl_receiver all_receivers [UDSL_NUMBER_RCV_URBS]; + + spinlock_t spare_receivers_lock; + struct list_head spare_receivers; + + spinlock_t completed_receivers_lock; + struct list_head completed_receivers; + + struct tasklet_struct receive_tasklet; + + /* sending */ + struct udsl_sender all_senders [UDSL_NUMBER_SND_URBS]; + struct udsl_send_buffer all_buffers [UDSL_NUMBER_SND_BUFS]; + + struct sk_buff_head sndqueue; + + spinlock_t send_lock; + struct list_head spare_senders; + struct list_head spare_buffers; + + struct tasklet_struct send_tasklet; + struct sk_buff *current_skb; /* being emptied */ + struct udsl_send_buffer *current_buffer; /* being filled */ + struct list_head filled_buffers; +}; + +static const char udsl_driver_name [] = "speedtch"; + +/* + * atm driver prototypes and structures + */ + +static void udsl_atm_dev_close (struct atm_dev *dev); +static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci); +static void udsl_atm_close (struct atm_vcc *vcc); +static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg); +static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb); +static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page); + +static struct atmdev_ops udsl_atm_devops = { + .dev_close = udsl_atm_dev_close, + .open = udsl_atm_open, + .close = udsl_atm_close, + .ioctl = udsl_atm_ioctl, + .send = udsl_atm_send, + .proc_read = udsl_atm_proc_read, +}; + +/* + * usb driver prototypes and structures + */ +static int udsl_usb_probe (struct usb_interface *intf, + const struct usb_device_id *id); +static void udsl_usb_disconnect (struct usb_interface *intf); +static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *user_data); + +static struct usb_driver udsl_usb_driver = { + .name = udsl_driver_name, + .probe = udsl_usb_probe, + .disconnect = udsl_usb_disconnect, + .ioctl = udsl_usb_ioctl, + .id_table = udsl_usb_ids, +}; + + +/************* +** decode ** +*************/ + +#define ATM_HDR_VPVC_MASK (ATM_HDR_VPI_MASK | ATM_HDR_VCI_MASK) +#define ATMSAR_USE_53BYTE_CELL 0x1L + +struct sk_buff *atmsar_decode_rawcell (struct atmsar_vcc_data *list, struct sk_buff *skb, + struct atmsar_vcc_data **ctx) +{ + while (skb->len) { + unsigned char *cell = skb->data; + unsigned char *cell_payload; + struct atmsar_vcc_data *vcc = list; + unsigned long atmHeader = + ((unsigned long) (cell[0]) << 24) | ((unsigned long) (cell[1]) << 16) | + ((unsigned long) (cell[2]) << 8) | (cell[3] & 0xff); + + dbg ("atmsar_decode_rawcell (0x%p, 0x%p, 0x%p) called", list, skb, ctx); + dbg ("atmsar_decode_rawcell skb->data %p, skb->tail %p", skb->data, skb->tail); + + if (!list || !skb || !ctx) + return NULL; + if (!skb->data || !skb->tail) + return NULL; + + /* here should the header CRC check be... */ + + /* look up correct vcc */ + for (; + vcc + && ((vcc->atmHeader & ATM_HDR_VPVC_MASK) != (atmHeader & ATM_HDR_VPVC_MASK)); + vcc = vcc->next); + + dbg ("atmsar_decode_rawcell found vcc %p for packet on vp %d, vc %d", vcc, + (int) ((atmHeader & ATM_HDR_VPI_MASK) >> ATM_HDR_VPI_SHIFT), + (int) ((atmHeader & ATM_HDR_VCI_MASK) >> ATM_HDR_VCI_SHIFT)); + + if (vcc && (skb->len >= (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52))) { + cell_payload = cell + (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 5 : 4); + + switch (vcc->type) { + case ATM_AAL0: + /* case ATM_AAL1: when we have a decode AAL1 function... */ + { + struct sk_buff *tmp = dev_alloc_skb (vcc->mtu); + + if (tmp) { + memcpy (tmp->tail, cell_payload, 48); + skb_put (tmp, 48); + + if (vcc->stats) + atomic_inc (&vcc->stats->rx); + + skb_pull (skb, + (vcc-> + flags & ATMSAR_USE_53BYTE_CELL ? 53 : + 52)); + dbg + ("atmsar_decode_rawcell returns ATM_AAL0 pdu 0x%p with length %d", + tmp, tmp->len); + return tmp; + }; + } + break; + case ATM_AAL1: + case ATM_AAL2: + case ATM_AAL34: + /* not supported */ + break; + case ATM_AAL5: + if (!vcc->reasBuffer) + vcc->reasBuffer = dev_alloc_skb (vcc->mtu); + + /* if alloc fails, we just drop the cell. it is possible that we can still + * receive cells on other vcc's + */ + if (vcc->reasBuffer) { + /* if (buffer overrun) discard received cells until now */ + if ((vcc->reasBuffer->len) > (vcc->mtu - 48)) + skb_trim (vcc->reasBuffer, 0); + + /* copy data */ + memcpy (vcc->reasBuffer->tail, cell_payload, 48); + skb_put (vcc->reasBuffer, 48); + + /* check for end of buffer */ + if (cell[3] & 0x2) { + struct sk_buff *tmp; + + /* the aal5 buffer ends here, cut the buffer. */ + /* buffer will always have at least one whole cell, so */ + /* don't need to check return from skb_pull */ + skb_pull (skb, + (vcc-> + flags & ATMSAR_USE_53BYTE_CELL ? 53 : + 52)); + *ctx = vcc; + tmp = vcc->reasBuffer; + vcc->reasBuffer = NULL; + + dbg + ("atmsar_decode_rawcell returns ATM_AAL5 pdu 0x%p with length %d", + tmp, tmp->len); + return tmp; + } + } + break; + }; + /* flush the cell */ + /* buffer will always contain at least one whole cell, so don't */ + /* need to check return value from skb_pull */ + skb_pull (skb, (vcc->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52)); + } else { + /* If data is corrupt and skb doesn't hold a whole cell, flush the lot */ + if (skb_pull (skb, (list->flags & ATMSAR_USE_53BYTE_CELL ? 53 : 52)) == + NULL) + return NULL; + } + } + + return NULL; +}; + +struct sk_buff *atmsar_decode_aal5 (struct atmsar_vcc_data *ctx, struct sk_buff *skb) +{ + uint crc = 0xffffffff; + uint length, pdu_crc, pdu_length; + + dbg ("atmsar_decode_aal5 (0x%p, 0x%p) called", ctx, skb); + + if (skb->len && (skb->len % 48)) + return NULL; + + length = (skb->tail[-6] << 8) + skb->tail[-5]; + pdu_crc = + (skb->tail[-4] << 24) + (skb->tail[-3] << 16) + (skb->tail[-2] << 8) + skb->tail[-1]; + pdu_length = ((length + 47 + 8) / 48) * 48; + + dbg ("atmsar_decode_aal5: skb->len = %d, length = %d, pdu_crc = 0x%x, pdu_length = %d", + skb->len, length, pdu_crc, pdu_length); + + /* is skb long enough ? */ + if (skb->len < pdu_length) { + if (ctx->stats) + atomic_inc (&ctx->stats->rx_err); + return NULL; + } + + /* is skb too long ? */ + if (skb->len > pdu_length) { + dbg ("atmsar_decode_aal5: Warning: readjusting illeagl size %d -> %d", + skb->len, pdu_length); + /* buffer is too long. we can try to recover + * if we discard the first part of the skb. + * the crc will decide whether this was ok + */ + skb_pull (skb, skb->len - pdu_length); + } + + crc = ~crc32_be (crc, skb->data, pdu_length - 4); + + /* check crc */ + if (pdu_crc != crc) { + dbg ("atmsar_decode_aal5: crc check failed!"); + if (ctx->stats) + atomic_inc (&ctx->stats->rx_err); + return NULL; + } + + /* pdu is ok */ + skb_trim (skb, length); + + /* update stats */ + if (ctx->stats) + atomic_inc (&ctx->stats->rx); + + dbg ("atmsar_decode_aal5 returns pdu 0x%p with length %d", skb, skb->len); + return skb; +}; + + +/************* +** encode ** +*************/ + +static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) { + struct udsl_control *ctrl = UDSL_SKB (skb); + unsigned int i, zero_padding; + unsigned char zero = 0; + u32 crc; + + ctrl->atm_data.vcc = vcc; + ctrl->cell_header [0] = vcc->vpi >> 4; + ctrl->cell_header [1] = (vcc->vpi << 4) | (vcc->vci >> 12); + ctrl->cell_header [2] = vcc->vci >> 4; + ctrl->cell_header [3] = vcc->vci << 4; + ctrl->cell_header [4] = 0xec; + + ctrl->num_cells = (skb->len + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD; + ctrl->num_entire = skb->len / ATM_CELL_PAYLOAD; + + zero_padding = ctrl->num_cells * ATM_CELL_PAYLOAD - skb->len - ATM_AAL5_TRAILER; + + if (ctrl->num_entire + 1 < ctrl->num_cells) + ctrl->pdu_padding = zero_padding - (ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); + else + ctrl->pdu_padding = zero_padding; + + ctrl->aal5_trailer [0] = 0; /* UU = 0 */ + ctrl->aal5_trailer [1] = 0; /* CPI = 0 */ + ctrl->aal5_trailer [2] = skb->len >> 8; + ctrl->aal5_trailer [3] = skb->len; + + crc = crc32_be (~0, skb->data, skb->len); + for (i = 0; i < zero_padding; i++) + crc = crc32_be (crc, &zero, 1); + crc = crc32_be (crc, ctrl->aal5_trailer, 4); + crc = ~crc; + + ctrl->aal5_trailer [4] = crc >> 24; + ctrl->aal5_trailer [5] = crc >> 16; + ctrl->aal5_trailer [6] = crc >> 8; + ctrl->aal5_trailer [7] = crc; +} + +unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb, unsigned char **target_p) { + struct udsl_control *ctrl = UDSL_SKB (skb); + unsigned char *target = *target_p; + unsigned int nc, ne, i; + + dbg ("udsl_write_cells: howmany=%u, skb->len=%d, num_cells=%u, num_entire=%u, pdu_padding=%u", howmany, skb->len, ctrl->num_cells, ctrl->num_entire, ctrl->pdu_padding); + + nc = ctrl->num_cells; + ne = min (howmany, ctrl->num_entire); + + for (i = 0; i < ne; i++) { + memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); + target += ATM_CELL_HEADER; + memcpy (target, skb->data, ATM_CELL_PAYLOAD); + target += ATM_CELL_PAYLOAD; + __skb_pull (skb, ATM_CELL_PAYLOAD); + } + + ctrl->num_entire -= ne; + + if (!(ctrl->num_cells -= ne) || !(howmany -= ne)) + goto out; + + memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); + target += ATM_CELL_HEADER; + memcpy (target, skb->data, skb->len); + target += skb->len; + __skb_pull (skb, skb->len); + memset (target, 0, ctrl->pdu_padding); + target += ctrl->pdu_padding; + + if (--ctrl->num_cells) { + if (!--howmany) { + ctrl->pdu_padding = ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; + goto out; + } + + memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); + target += ATM_CELL_HEADER; + memset (target, 0, ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); + target += ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; + + if (--ctrl->num_cells) + BUG(); + } + + memcpy (target, ctrl->aal5_trailer, ATM_AAL5_TRAILER); + target += ATM_AAL5_TRAILER; + /* set pti bit in last cell */ + *(target + 3 - ATM_CELL_SIZE) |= 0x2; + +out: + *target_p = target; + return nc - ctrl->num_cells; +} + + +/************** +** receive ** +**************/ + +static void udsl_complete_receive (struct urb *urb, struct pt_regs *regs) +{ + struct udsl_instance_data *instance; + struct udsl_receiver *rcv; + unsigned long flags; + + if (!urb || !(rcv = urb->context) || !(instance = rcv->instance)) { + dbg ("udsl_complete_receive: bad urb!"); + return; + } + + dbg ("udsl_complete_receive entered (urb 0x%p, status %d)", urb, urb->status); + + /* may not be in_interrupt() */ + spin_lock_irqsave (&instance->completed_receivers_lock, flags); + list_add_tail (&rcv->list, &instance->completed_receivers); + tasklet_schedule (&instance->receive_tasklet); + spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); +} + +static void udsl_process_receive (unsigned long data) +{ + struct udsl_instance_data *instance = (struct udsl_instance_data *) data; + struct udsl_receiver *rcv; + unsigned long flags; + unsigned char *data_start; + struct sk_buff *skb; + struct urb *urb; + struct atmsar_vcc_data *atmsar_vcc = NULL; + struct sk_buff *new = NULL, *tmp = NULL; + int err; + + dbg ("udsl_process_receive entered"); + + spin_lock_irqsave (&instance->completed_receivers_lock, flags); + while (!list_empty (&instance->completed_receivers)) { + rcv = list_entry (instance->completed_receivers.next, struct udsl_receiver, list); + list_del (&rcv->list); + spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); + + urb = rcv->urb; + dbg ("udsl_process_receive: got packet %p with length %d and status %d", urb, urb->actual_length, urb->status); + + switch (urb->status) { + case 0: + dbg ("udsl_process_receive: processing urb with rcv %p, urb %p, skb %p", rcv, urb, rcv->skb); + + /* update the skb structure */ + skb = rcv->skb; + skb_trim (skb, 0); + skb_put (skb, urb->actual_length); + data_start = skb->data; + + dbg ("skb->len = %d", skb->len); + PACKETDEBUG (skb->data, skb->len); + + while ((new = + atmsar_decode_rawcell (instance->atmsar_vcc_list, skb, + &atmsar_vcc)) != NULL) { + dbg ("(after cell processing)skb->len = %d", new->len); + + switch (atmsar_vcc->type) { + case ATM_AAL5: + tmp = new; + new = atmsar_decode_aal5 (atmsar_vcc, new); + + /* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */ + if (new) { + dbg ("(after aal5 decap) skb->len = %d", new->len); + if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) { + PACKETDEBUG (new->data, new->len); + atmsar_vcc->vcc->push (atmsar_vcc->vcc, new); + } else { + dbg + ("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d", + atomic_read (&atmsar_vcc->vcc->rx_inuse), + atmsar_vcc->vcc->sk->rcvbuf, new->truesize); + dev_kfree_skb (new); + } + } else { + dbg ("atmsar_decode_aal5 returned NULL!"); + dev_kfree_skb (tmp); + } + break; + default: + /* not supported. we delete the skb. */ + printk (KERN_INFO + "SpeedTouch USB: illegal vcc type. Dropping packet.\n"); + dev_kfree_skb (new); + break; + } + } + + /* restore skb */ + skb_push (skb, skb->data - data_start); + + usb_fill_bulk_urb (urb, + instance->usb_dev, + usb_rcvbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_IN), + (unsigned char *) rcv->skb->data, + UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE, + udsl_complete_receive, + rcv); + if (!(err = usb_submit_urb (urb, GFP_ATOMIC))) + break; + dbg ("udsl_process_receive: submission failed (%d)", err); + /* fall through */ + default: /* error or urb unlinked */ + dbg ("udsl_process_receive: adding to spare_receivers"); + spin_lock_irqsave (&instance->spare_receivers_lock, flags); + list_add (&rcv->list, &instance->spare_receivers); + spin_unlock_irqrestore (&instance->spare_receivers_lock, flags); + break; + } /* switch */ + + spin_lock_irqsave (&instance->completed_receivers_lock, flags); + } /* while */ + spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); + dbg ("udsl_process_receive successful"); +} + +static void udsl_fire_receivers (struct udsl_instance_data *instance) +{ + struct list_head receivers, *pos, *n; + unsigned long flags; + + INIT_LIST_HEAD (&receivers); + + down (&instance->serialize); + + spin_lock_irqsave (&instance->spare_receivers_lock, flags); + list_splice_init (&instance->spare_receivers, &receivers); + spin_unlock_irqrestore (&instance->spare_receivers_lock, flags); + + list_for_each_safe (pos, n, &receivers) { + struct udsl_receiver *rcv = list_entry (pos, struct udsl_receiver, list); + + dbg ("udsl_fire_receivers: firing urb %p", rcv->urb); + + usb_fill_bulk_urb (rcv->urb, + instance->usb_dev, + usb_rcvbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_IN), + (unsigned char *) rcv->skb->data, + UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE, + udsl_complete_receive, + rcv); + + if (usb_submit_urb (rcv->urb, GFP_KERNEL) < 0) { + dbg ("udsl_fire_receivers: submit failed!"); + spin_lock_irqsave (&instance->spare_receivers_lock, flags); + list_move (pos, &instance->spare_receivers); + spin_unlock_irqrestore (&instance->spare_receivers_lock, flags); + } + } + + up (&instance->serialize); +} + + +/*********** +** send ** +***********/ + +static void udsl_complete_send (struct urb *urb, struct pt_regs *regs) +{ + struct udsl_instance_data *instance; + struct udsl_sender *snd; + unsigned long flags; + + if (!urb || !(snd = urb->context) || !(instance = snd->instance)) { + dbg ("udsl_complete_send: bad urb!"); + return; + } + + dbg ("udsl_complete_send entered (urb 0x%p, status %d)", urb, urb->status); + + /* may not be in_interrupt() */ + spin_lock_irqsave (&instance->send_lock, flags); + list_add (&snd->list, &instance->spare_senders); + list_add (&snd->buffer->list, &instance->spare_buffers); + tasklet_schedule (&instance->send_tasklet); + spin_unlock_irqrestore (&instance->send_lock, flags); +} + +static void udsl_process_send (unsigned long data) +{ + struct udsl_send_buffer *buf; + int err; + unsigned long flags; + struct udsl_instance_data *instance = (struct udsl_instance_data *) data; + unsigned int num_written; + struct sk_buff *skb; + struct udsl_sender *snd; + + dbg ("udsl_process_send entered"); + +made_progress: + spin_lock_irqsave (&instance->send_lock, flags); + while (!list_empty (&instance->spare_senders)) { + if (!list_empty (&instance->filled_buffers)) { + buf = list_entry (instance->filled_buffers.next, struct udsl_send_buffer, list); + list_del (&buf->list); + dbg ("sending filled buffer (0x%p)", buf); + } else if ((buf = instance->current_buffer)) { + instance->current_buffer = NULL; + dbg ("sending current buffer (0x%p)", buf); + } else /* all buffers empty */ + break; + + snd = list_entry (instance->spare_senders.next, struct udsl_sender, list); + list_del (&snd->list); + spin_unlock_irqrestore (&instance->send_lock, flags); + + snd->buffer = buf; + usb_fill_bulk_urb (snd->urb, + instance->usb_dev, + usb_sndbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_OUT), + buf->base, + (UDSL_SND_BUFFER_SIZE - buf->free_cells) * ATM_CELL_SIZE, + udsl_complete_send, + snd); + + dbg ("submitting urb 0x%p, contains %d cells", snd->urb, UDSL_SND_BUFFER_SIZE - buf->free_cells); + + if ((err = usb_submit_urb(snd->urb, GFP_ATOMIC)) < 0) { + dbg ("submission failed (%d)!", err); + spin_lock_irqsave (&instance->send_lock, flags); + list_add (&snd->list, &instance->spare_senders); + spin_unlock_irqrestore (&instance->send_lock, flags); + list_add (&buf->list, &instance->filled_buffers); + return; + } + + spin_lock_irqsave (&instance->send_lock, flags); + } /* while */ + spin_unlock_irqrestore (&instance->send_lock, flags); + + if (!instance->current_skb && !(instance->current_skb = skb_dequeue (&instance->sndqueue))) { + dbg ("done - no more skbs"); + return; + } + + skb = instance->current_skb; + + if (!(buf = instance->current_buffer)) { + spin_lock_irqsave (&instance->send_lock, flags); + if (list_empty (&instance->spare_buffers)) { + instance->current_buffer = NULL; + spin_unlock_irqrestore (&instance->send_lock, flags); + dbg ("done - no more buffers"); + return; + } + buf = list_entry (instance->spare_buffers.next, struct udsl_send_buffer, list); + list_del (&buf->list); + spin_unlock_irqrestore (&instance->send_lock, flags); + + buf->free_start = buf->base; + buf->free_cells = UDSL_SND_BUFFER_SIZE; + + instance->current_buffer = buf; + } + + num_written = udsl_write_cells (buf->free_cells, skb, &buf->free_start); + + dbg ("wrote %u cells from skb 0x%p to buffer 0x%p", num_written, skb, buf); + + if (!(buf->free_cells -= num_written)) { + list_add_tail (&buf->list, &instance->filled_buffers); + instance->current_buffer = NULL; + dbg ("queued filled buffer"); + } + + dbg ("buffer contains %d cells, %d left", UDSL_SND_BUFFER_SIZE - buf->free_cells, buf->free_cells); + + if (!UDSL_SKB (skb)->num_cells) { + struct atm_vcc *vcc = UDSL_SKB (skb)->atm_data.vcc; + + dbg ("discarding empty skb"); + if (vcc->pop) + vcc->pop (vcc, skb); + else + kfree_skb (skb); + instance->current_skb = NULL; + + if (vcc->stats) + atomic_inc (&vcc->stats->tx); + } + + goto made_progress; +} + +static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vcc *vcc) +{ + unsigned long flags; + struct sk_buff *skb, *n; + + dbg ("udsl_cancel_send entered"); + spin_lock_irqsave (&instance->sndqueue.lock, flags); + for (skb = instance->sndqueue.next, n = skb->next; skb != (struct sk_buff *)&instance->sndqueue; skb = n, n = skb->next) + if (UDSL_SKB (skb)->atm_data.vcc == vcc) { + dbg ("popping skb 0x%p", skb); + __skb_unlink (skb, &instance->sndqueue); + if (vcc->pop) + vcc->pop (vcc, skb); + else + kfree_skb (skb); + } + spin_unlock_irqrestore (&instance->sndqueue.lock, flags); + + tasklet_disable (&instance->send_tasklet); + if ((skb = instance->current_skb) && (UDSL_SKB (skb)->atm_data.vcc == vcc)) { + dbg ("popping current skb (0x%p)", skb); + instance->current_skb = NULL; + if (vcc->pop) + vcc->pop (vcc, skb); + else + kfree_skb (skb); + } + tasklet_enable (&instance->send_tasklet); + dbg ("udsl_cancel_send done"); +} + +static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb) +{ + struct udsl_instance_data *instance = vcc->dev->dev_data; + + dbg ("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len); + + if (!instance || !instance->usb_dev) { + dbg ("NULL data!"); + return -ENODEV; + } + + if (!instance->firmware_loaded) + return -EAGAIN; + + if (vcc->qos.aal != ATM_AAL5) { + dbg ("unsupported ATM type %d!", vcc->qos.aal); + return -EINVAL; + } + + if (skb->len > ATM_MAX_AAL5_PDU) { + dbg ("packet too long (%d vs %d)!", skb->len, ATM_MAX_AAL5_PDU); + return -EINVAL; + } + + PACKETDEBUG (skb->data, skb->len); + + udsl_groom_skb (vcc, skb); + skb_queue_tail (&instance->sndqueue, skb); + tasklet_schedule (&instance->send_tasklet); + + return 0; +} + + +/********** +** ATM ** +**********/ + +#define ATMSAR_DEF_MTU_AAL0 48 +#define ATMSAR_DEF_MTU_AAL1 47 +#define ATMSAR_DEF_MTU_AAL2 0 /* not supported */ +#define ATMSAR_DEF_MTU_AAL34 0 /* not supported */ +#define ATMSAR_DEF_MTU_AAL5 65535 /* max mtu .. */ + +struct atmsar_vcc_data *atmsar_open (struct atmsar_vcc_data **list, struct atm_vcc *vcc, uint type, + ushort vpi, ushort vci, unchar pti, unchar gfc, uint flags) +{ + struct atmsar_vcc_data *new; + + if (!vcc) + return NULL; + + new = kmalloc (sizeof (struct atmsar_vcc_data), GFP_KERNEL); + + if (!new) + return NULL; + + memset (new, 0, sizeof (struct atmsar_vcc_data)); + new->vcc = vcc; + new->stats = vcc->stats; + new->type = type; + new->next = NULL; + new->gfc = gfc; + new->vp = vpi; + new->vc = vci; + new->pti = pti; + + switch (type) { + case ATM_AAL0: + new->mtu = ATMSAR_DEF_MTU_AAL0; + break; + case ATM_AAL1: + new->mtu = ATMSAR_DEF_MTU_AAL1; + break; + case ATM_AAL2: + new->mtu = ATMSAR_DEF_MTU_AAL2; + break; + case ATM_AAL34: + /* not supported */ + new->mtu = ATMSAR_DEF_MTU_AAL34; + break; + case ATM_AAL5: + new->mtu = ATMSAR_DEF_MTU_AAL5; + break; + } + + new->atmHeader = ((unsigned long) gfc << ATM_HDR_GFC_SHIFT) + | ((unsigned long) vpi << ATM_HDR_VPI_SHIFT) + | ((unsigned long) vci << ATM_HDR_VCI_SHIFT) + | ((unsigned long) pti << ATM_HDR_PTI_SHIFT); + new->flags = flags; + new->next = NULL; + new->reasBuffer = NULL; + + new->next = *list; + *list = new; + + dbg ("Allocated new SARLib vcc 0x%p with vp %d vc %d", new, vpi, vci); + + return new; +} + +void atmsar_close (struct atmsar_vcc_data **list, struct atmsar_vcc_data *vcc) +{ + struct atmsar_vcc_data *work; + + if (*list == vcc) { + *list = (*list)->next; + } else { + for (work = *list; work && work->next && (work->next != vcc); work = work->next); + + /* return if not found */ + if (work->next != vcc) + return; + + work->next = work->next->next; + } + + if (vcc->reasBuffer) { + dev_kfree_skb (vcc->reasBuffer); + } + + dbg ("Allocated SARLib vcc 0x%p with vp %d vc %d", vcc, vcc->vp, vcc->vc); + + kfree (vcc); +} + +static void udsl_atm_dev_close (struct atm_dev *dev) +{ + struct udsl_instance_data *instance = dev->dev_data; + + if (!instance) { + dbg ("udsl_atm_dev_close: NULL instance!"); + return; + } + + dbg ("udsl_atm_dev_close: queue has %u elements", instance->sndqueue.qlen); + + dbg ("udsl_atm_dev_close: killing tasklet"); + tasklet_kill (&instance->send_tasklet); + dbg ("udsl_atm_dev_close: freeing instance"); + kfree (instance); + dev->dev_data = NULL; +} + +static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page) +{ + struct udsl_instance_data *instance = atm_dev->dev_data; + int left = *pos; + + if (!instance) { + dbg ("NULL instance!"); + return -ENODEV; + } + + if (!left--) + return sprintf (page, "%s\n", instance->description); + + if (!left--) + return sprintf (page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", + atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2], + atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]); + + if (!left--) + return sprintf (page, "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n", + atomic_read (&atm_dev->stats.aal5.tx), + atomic_read (&atm_dev->stats.aal5.tx_err), + atomic_read (&atm_dev->stats.aal5.rx), + atomic_read (&atm_dev->stats.aal5.rx_err), + atomic_read (&atm_dev->stats.aal5.rx_drop)); + + if (!left--) { + switch (atm_dev->signal) { + case ATM_PHY_SIG_FOUND: + sprintf (page, "Line up"); + break; + case ATM_PHY_SIG_LOST: + sprintf (page, "Line down"); + break; + default: + sprintf (page, "Line state unknown"); + break; + } + + if (instance->usb_dev) { + if (!instance->firmware_loaded) + strcat (page, ", no firmware\n"); + else + strcat (page, ", firmware loaded\n"); + } else + strcat (page, ", disconnected\n"); + + return strlen (page); + } + + return 0; +} + +#define ATMSAR_SET_PTI 0x2L + +static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci) +{ + struct udsl_instance_data *instance = vcc->dev->dev_data; + + dbg ("udsl_atm_open called"); + + if (!instance || !instance->usb_dev) { + dbg ("NULL data!"); + return -ENODEV; + } + + /* at the moment only AAL5 support */ + if (vcc->qos.aal != ATM_AAL5) + return -EINVAL; + + MOD_INC_USE_COUNT; + + vcc->dev_data = + atmsar_open (&(instance->atmsar_vcc_list), vcc, ATM_AAL5, vpi, vci, 0, 0, + ATMSAR_USE_53BYTE_CELL | ATMSAR_SET_PTI); + if (!vcc->dev_data) { + MOD_DEC_USE_COUNT; + return -ENOMEM; /* this is the only reason atmsar_open can fail... */ + } + + vcc->vpi = vpi; + vcc->vci = vci; + set_bit (ATM_VF_ADDR, &vcc->flags); + set_bit (ATM_VF_PARTIAL, &vcc->flags); + set_bit (ATM_VF_READY, &vcc->flags); + + ((struct atmsar_vcc_data *)vcc->dev_data)->mtu = UDSL_MAX_AAL5_MRU; + + if (instance->firmware_loaded) + udsl_fire_receivers (instance); + + dbg ("udsl_atm_open successful"); + return 0; +} + +static void udsl_atm_close (struct atm_vcc *vcc) +{ + struct udsl_instance_data *instance = vcc->dev->dev_data; + + dbg ("udsl_atm_close called"); + + if (!instance) { + dbg ("NULL instance!"); + return; + } + + /* freeing resources */ + /* cancel all sends on this vcc */ + udsl_cancel_send (instance, vcc); + + atmsar_close (&(instance->atmsar_vcc_list), vcc->dev_data); + vcc->dev_data = NULL; + clear_bit (ATM_VF_PARTIAL, &vcc->flags); + + /* freeing address */ + vcc->vpi = ATM_VPI_UNSPEC; + vcc->vci = ATM_VCI_UNSPEC; + clear_bit (ATM_VF_ADDR, &vcc->flags); + + MOD_DEC_USE_COUNT; + + dbg ("udsl_atm_close successful"); + return; +} + +static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg) +{ + switch (cmd) { + case ATM_QUERYLOOP: + return put_user (ATM_LM_NONE, (int *) arg) ? -EFAULT : 0; + default: + return -ENOIOCTLCMD; + } +} + + +/********** +** USB ** +**********/ + +static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *user_data) +{ + struct udsl_instance_data *instance = usb_get_intfdata (intf); + + dbg ("udsl_usb_ioctl entered"); + + if (!instance) { + dbg ("NULL instance!"); + return -ENODEV; + } + + switch (code) { + case UDSL_IOCTL_START: + instance->atm_dev->signal = ATM_PHY_SIG_FOUND; + down (&instance->serialize); /* vs self */ + if (!instance->firmware_loaded) { + usb_set_interface (instance->usb_dev, 1, 1); + instance->firmware_loaded = 1; + } + up (&instance->serialize); + udsl_fire_receivers (instance); + return 0; + case UDSL_IOCTL_STOP: + instance->atm_dev->signal = ATM_PHY_SIG_LOST; + return 0; + default: + return -ENOTTY; + } +} + +static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(intf); + int ifnum = intf->altsetting->desc.bInterfaceNumber; + struct udsl_instance_data *instance; + unsigned char mac_str [13]; + int i, length; + char *buf; + + dbg ("Trying device with Vendor=0x%x, Product=0x%x, ifnum %d", + dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); + + if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || + (dev->descriptor.idVendor != SPEEDTOUCH_VENDORID) || + (dev->descriptor.idProduct != SPEEDTOUCH_PRODUCTID) || (ifnum != 1)) + return -ENODEV; + + dbg ("Device Accepted"); + + /* instance init */ + if (!(instance = kmalloc (sizeof (struct udsl_instance_data), GFP_KERNEL))) { + dbg ("No memory for Instance data!"); + return -ENOMEM; + } + + memset (instance, 0, sizeof (struct udsl_instance_data)); + + init_MUTEX (&instance->serialize); + + instance->usb_dev = dev; + + spin_lock_init (&instance->spare_receivers_lock); + INIT_LIST_HEAD (&instance->spare_receivers); + + spin_lock_init (&instance->completed_receivers_lock); + INIT_LIST_HEAD (&instance->completed_receivers); + + tasklet_init (&instance->receive_tasklet, udsl_process_receive, (unsigned long) instance); + + skb_queue_head_init (&instance->sndqueue); + + spin_lock_init (&instance->send_lock); + INIT_LIST_HEAD (&instance->spare_senders); + INIT_LIST_HEAD (&instance->spare_buffers); + + tasklet_init (&instance->send_tasklet, udsl_process_send, (unsigned long) instance); + INIT_LIST_HEAD (&instance->filled_buffers); + + /* receive init */ + for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { + struct udsl_receiver *rcv = &(instance->all_receivers[i]); + + if (!(rcv->skb = dev_alloc_skb (UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE))) { + dbg ("No memory for skb %d!", i); + goto fail; + } + + if (!(rcv->urb = usb_alloc_urb (0, GFP_KERNEL))) { + dbg ("No memory for receive urb %d!", i); + goto fail; + } + + rcv->instance = instance; + + list_add (&rcv->list, &instance->spare_receivers); + + dbg ("skb->truesize = %d (asked for %d)", rcv->skb->truesize, UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE); + } + + /* send init */ + for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) { + struct udsl_sender *snd = &(instance->all_senders[i]); + + if (!(snd->urb = usb_alloc_urb (0, GFP_KERNEL))) { + dbg ("No memory for send urb %d!", i); + goto fail; + } + + snd->instance = instance; + + list_add (&snd->list, &instance->spare_senders); + } + + for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) { + struct udsl_send_buffer *buf = &(instance->all_buffers[i]); + + if (!(buf->base = kmalloc (UDSL_SND_BUFFER_SIZE * ATM_CELL_SIZE, GFP_KERNEL))) { + dbg ("No memory for send buffer %d!", i); + goto fail; + } + + list_add (&buf->list, &instance->spare_buffers); + } + + /* atm init */ + if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, &udsl_atm_devops, -1, 0))) { + dbg ("failed to register ATM device!"); + goto fail; + } + + instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX; + instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX; + instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN; + + /* tmp init atm device, set to 128kbit */ + instance->atm_dev->link_rate = 128 * 1000 / 424; + + /* set MAC address, it is stored in the serial number */ + memset (instance->atm_dev->esi, 0, sizeof (instance->atm_dev->esi)); + if (usb_string (dev, dev->descriptor.iSerialNumber, mac_str, sizeof (mac_str)) == 12) + for (i = 0; i < 6; i++) + instance->atm_dev->esi[i] = (hex2int (mac_str[i * 2]) * 16) + (hex2int (mac_str[i * 2 + 1])); + + /* device description */ + buf = instance->description; + length = sizeof (instance->description); + + if ((i = usb_string (dev, dev->descriptor.iProduct, buf, length)) < 0) + goto finish; + + buf += i; + length -= i; + + i = snprintf (buf, length, " ("); + buf += i; + length -= i; + + if (length <= 0 || (i = usb_make_path (dev, buf, length)) < 0) + goto finish; + + buf += i; + length -= i; + + snprintf (buf, length, ")"); + +finish: + /* ready for ATM callbacks */ + instance->atm_dev->dev_data = instance; + + usb_set_intfdata (intf, instance); + + return 0; + +fail: + for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) + kfree (instance->all_buffers[i].base); + + for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) + usb_free_urb (instance->all_senders[i].urb); + + for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { + struct udsl_receiver *rcv = &(instance->all_receivers[i]); + + usb_free_urb (rcv->urb); + + if (rcv->skb) + kfree_skb (rcv->skb); + } + + kfree (instance); + + return -ENOMEM; +} + +static void udsl_usb_disconnect (struct usb_interface *intf) +{ + struct udsl_instance_data *instance = usb_get_intfdata (intf); + struct list_head *pos; + unsigned long flags; + unsigned int count = 0; + int result, i; + + dbg ("disconnecting"); + + usb_set_intfdata (intf, NULL); + + if (!instance) { + dbg ("NULL instance!"); + return; + } + + tasklet_disable (&instance->receive_tasklet); + + /* receive finalize */ + down (&instance->serialize); /* vs udsl_fire_receivers */ + /* no need to take the spinlock */ + list_for_each (pos, &instance->spare_receivers) + if (++count > UDSL_NUMBER_RCV_URBS) + panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); + INIT_LIST_HEAD (&instance->spare_receivers); + up (&instance->serialize); + + dbg ("udsl_usb_disconnect: flushed %u spare receivers", count); + + count = UDSL_NUMBER_RCV_URBS - count; + + for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) + if ((result = usb_unlink_urb (instance->all_receivers[i].urb)) < 0) + dbg ("udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d", i, result); + + /* wait for completion handlers to finish */ + do { + unsigned int completed = 0; + + spin_lock_irqsave (&instance->completed_receivers_lock, flags); + list_for_each (pos, &instance->completed_receivers) + if (++completed > count) + panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); + spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); + + dbg ("udsl_usb_disconnect: found %u completed receivers", completed); + + if (completed == count) + break; + + yield (); + } while (1); + + dbg ("udsl_usb_disconnect: flushing"); + /* no need to take the spinlock */ + INIT_LIST_HEAD (&instance->completed_receivers); + + tasklet_enable (&instance->receive_tasklet); + tasklet_kill (&instance->receive_tasklet); + + dbg ("udsl_usb_disconnect: freeing receivers"); + for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { + struct udsl_receiver *rcv = &(instance->all_receivers[i]); + + usb_free_urb (rcv->urb); + kfree_skb (rcv->skb); + } + + /* send finalize */ + tasklet_disable (&instance->send_tasklet); + + for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) + if ((result = usb_unlink_urb (instance->all_senders[i].urb)) < 0) + dbg ("udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d", i, result); + + /* wait for completion handlers to finish */ + do { + count = 0; + spin_lock_irqsave (&instance->send_lock, flags); + list_for_each (pos, &instance->spare_senders) + if (++count > UDSL_NUMBER_SND_URBS) + panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); + spin_unlock_irqrestore (&instance->send_lock, flags); + + dbg ("udsl_usb_disconnect: found %u spare senders", count); + + if (count == UDSL_NUMBER_SND_URBS) + break; + + yield (); + } while (1); + + dbg ("udsl_usb_disconnect: flushing"); + /* no need to take the spinlock */ + INIT_LIST_HEAD (&instance->spare_senders); + INIT_LIST_HEAD (&instance->spare_buffers); + instance->current_buffer = NULL; + + tasklet_enable (&instance->send_tasklet); + + dbg ("udsl_usb_disconnect: freeing senders"); + for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) + usb_free_urb (instance->all_senders[i].urb); + + dbg ("udsl_usb_disconnect: freeing buffers"); + for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) + kfree (instance->all_buffers[i].base); + + instance->usb_dev = NULL; + + /* atm finalize */ + shutdown_atm_dev (instance->atm_dev); /* frees instance */ +} + + +/*********** +** init ** +***********/ + +static int __init udsl_usb_init (void) +{ + struct sk_buff *skb; /* dummy for sizeof */ + + dbg ("udsl_usb_init: driver version " DRIVER_VERSION); + + if (sizeof (struct udsl_control) > sizeof (skb->cb)) { + printk (KERN_ERR __FILE__ ": unusable with this kernel!\n"); + return -EIO; + } + + return usb_register (&udsl_usb_driver); +} + +static void __exit udsl_usb_cleanup (void) +{ + dbg ("udsl_usb_cleanup"); + + usb_deregister (&udsl_usb_driver); +} + +module_init (udsl_usb_init); +module_exit (udsl_usb_cleanup); + +MODULE_AUTHOR (DRIVER_AUTHOR); +MODULE_DESCRIPTION (DRIVER_DESC); +MODULE_LICENSE ("GPL"); + + +/************ +** debug ** +************/ + +#ifdef DEBUG_PACKET +static int udsl_print_packet (const unsigned char *data, int len) +{ + unsigned char buffer [256]; + int i = 0, j = 0; + + for (i = 0; i < len;) { + buffer[0] = '\0'; + sprintf (buffer, "%.3d :", i); + for (j = 0; (j < 16) && (i < len); j++, i++) { + sprintf (buffer, "%s %2.2x", buffer, data[i]); + } + dbg ("%s", buffer); + } + return i; +} +#endif diff --git a/drivers/usb/misc/speedtouch.c b/drivers/usb/misc/speedtouch.c deleted file mode 100644 index d474877b03c0..000000000000 --- a/drivers/usb/misc/speedtouch.c +++ /dev/null @@ -1,1216 +0,0 @@ -/****************************************************************************** - * speedtouch.c -- Alcatel SpeedTouch USB xDSL modem driver. - * - * Copyright (C) 2001, Alcatel - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - ******************************************************************************/ - -/* - * Written by Johan Verrept (Johan.Verrept@advalvas.be) - * - * 1.5A: - Version for inclusion in 2.5 series kernel - * - Modifications by Richard Purdie (rpurdie@rpsys.net) - * - made compatible with kernel 2.5.6 onwards by changing - * udsl_usb_send_data_context->urb to a pointer and adding code - * to alloc and free it - * - remove_wait_queue() added to udsl_atm_processqueue_thread() - * - * 1.5: - fixed memory leak when atmsar_decode_aal5 returned NULL. - * (reported by stephen.robinson@zen.co.uk) - * - * 1.4: - changed the spin_lock() under interrupt to spin_lock_irqsave() - * - unlink all active send urbs of a vcc that is being closed. - * - * 1.3.1: - added the version number - * - * 1.3: - Added multiple send urb support - * - fixed memory leak and vcc->tx_inuse starvation bug - * when not enough memory left in vcc. - * - * 1.2: - Fixed race condition in udsl_usb_send_data() - * 1.1: - Turned off packet debugging - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "atmsar.h" - -/* -#define DEBUG 1 -#define DEBUG_PACKET 1 -*/ - -#include - - -#ifdef DEBUG_PACKET -static int udsl_print_packet (const unsigned char *data, int len); -#define PACKETDEBUG(arg...) udsl_print_packet (arg) -#else -#define PACKETDEBUG(arg...) -#endif - -#define DRIVER_AUTHOR "Johan Verrept, Johan.Verrept@advalvas.be" -#define DRIVER_DESC "Driver for the Alcatel SpeedTouch USB ADSL modem" -#define DRIVER_VERSION "1.5A" - -#define SPEEDTOUCH_VENDORID 0x06b9 -#define SPEEDTOUCH_PRODUCTID 0x4061 - -#define UDSL_NUMBER_RCV_URBS 1 -#define UDSL_NUMBER_SND_URBS 1 -#define UDSL_NUMBER_SND_BUFS (2*UDSL_NUMBER_SND_URBS) -#define UDSL_RCV_BUFFER_SIZE (1*64) /* ATM cells */ -#define UDSL_SND_BUFFER_SIZE (1*64) /* ATM cells */ -/* max should be (1500 IP mtu + 2 ppp bytes + 32 * 5 cellheader overhead) for - * PPPoA and (1500 + 14 + 32*5 cellheader overhead) for PPPoE */ -#define UDSL_MAX_AAL5_MRU 2048 - -#define UDSL_IOCTL_START 1 -#define UDSL_IOCTL_STOP 2 - -/* endpoint declarations */ - -#define UDSL_ENDPOINT_DATA_OUT 0x07 -#define UDSL_ENDPOINT_DATA_IN 0x87 - -#define hex2int(c) ( (c >= '0')&&(c <= '9') ? (c - '0') : ((c & 0xf)+9) ) - -/* usb_device_id struct */ - -static struct usb_device_id udsl_usb_ids [] = { - { USB_DEVICE (SPEEDTOUCH_VENDORID, SPEEDTOUCH_PRODUCTID) }, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE (usb, udsl_usb_ids); - -/* context declarations */ - -struct udsl_receiver { - struct list_head list; - struct sk_buff *skb; - struct urb *urb; - struct udsl_instance_data *instance; -}; - -struct udsl_send_buffer { - struct list_head list; - unsigned char *base; - unsigned char *free_start; - unsigned int free_cells; -}; - -struct udsl_sender { - struct list_head list; - struct udsl_send_buffer *buffer; - struct urb *urb; - struct udsl_instance_data *instance; -}; - -struct udsl_control { - struct atm_skb_data atm_data; - unsigned int num_cells; - unsigned int num_entire; - unsigned char cell_header [ATM_CELL_HEADER]; - unsigned int pdu_padding; - unsigned char aal5_trailer [ATM_AAL5_TRAILER]; -}; - -#define UDSL_SKB(x) ((struct udsl_control *)(x)->cb) - -/* - * UDSL main driver data - */ - -struct udsl_instance_data { - struct semaphore serialize; - - /* usb device part */ - struct usb_device *usb_dev; - char description [64]; - int firmware_loaded; - - /* atm device part */ - struct atm_dev *atm_dev; - struct atmsar_vcc_data *atmsar_vcc_list; - - /* receiving */ - struct udsl_receiver all_receivers [UDSL_NUMBER_RCV_URBS]; - - spinlock_t spare_receivers_lock; - struct list_head spare_receivers; - - spinlock_t completed_receivers_lock; - struct list_head completed_receivers; - - struct tasklet_struct receive_tasklet; - - /* sending */ - struct udsl_sender all_senders [UDSL_NUMBER_SND_URBS]; - struct udsl_send_buffer all_buffers [UDSL_NUMBER_SND_BUFS]; - - struct sk_buff_head sndqueue; - - spinlock_t send_lock; - struct list_head spare_senders; - struct list_head spare_buffers; - - struct tasklet_struct send_tasklet; - struct sk_buff *current_skb; /* being emptied */ - struct udsl_send_buffer *current_buffer; /* being filled */ - struct list_head filled_buffers; -}; - -static const char udsl_driver_name [] = "speedtch"; - -/* - * atm driver prototypes and structures - */ - -static void udsl_atm_dev_close (struct atm_dev *dev); -static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci); -static void udsl_atm_close (struct atm_vcc *vcc); -static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg); -static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb); -static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page); - -static struct atmdev_ops udsl_atm_devops = { - .dev_close = udsl_atm_dev_close, - .open = udsl_atm_open, - .close = udsl_atm_close, - .ioctl = udsl_atm_ioctl, - .send = udsl_atm_send, - .proc_read = udsl_atm_proc_read, -}; - -/* - * usb driver prototypes and structures - */ -static int udsl_usb_probe (struct usb_interface *intf, - const struct usb_device_id *id); -static void udsl_usb_disconnect (struct usb_interface *intf); -static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *user_data); - -static struct usb_driver udsl_usb_driver = { - .name = udsl_driver_name, - .probe = udsl_usb_probe, - .disconnect = udsl_usb_disconnect, - .ioctl = udsl_usb_ioctl, - .id_table = udsl_usb_ids, -}; - - -/************* -** encode ** -*************/ - -static void udsl_groom_skb (struct atm_vcc *vcc, struct sk_buff *skb) { - struct udsl_control *ctrl = UDSL_SKB (skb); - unsigned int i, zero_padding; - unsigned char zero = 0; - u32 crc; - - ctrl->atm_data.vcc = vcc; - ctrl->cell_header [0] = vcc->vpi >> 4; - ctrl->cell_header [1] = (vcc->vpi << 4) | (vcc->vci >> 12); - ctrl->cell_header [2] = vcc->vci >> 4; - ctrl->cell_header [3] = vcc->vci << 4; - ctrl->cell_header [4] = 0xec; - - ctrl->num_cells = (skb->len + ATM_AAL5_TRAILER + ATM_CELL_PAYLOAD - 1) / ATM_CELL_PAYLOAD; - ctrl->num_entire = skb->len / ATM_CELL_PAYLOAD; - - zero_padding = ctrl->num_cells * ATM_CELL_PAYLOAD - skb->len - ATM_AAL5_TRAILER; - - if (ctrl->num_entire + 1 < ctrl->num_cells) - ctrl->pdu_padding = zero_padding - (ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); - else - ctrl->pdu_padding = zero_padding; - - ctrl->aal5_trailer [0] = 0; /* UU = 0 */ - ctrl->aal5_trailer [1] = 0; /* CPI = 0 */ - ctrl->aal5_trailer [2] = skb->len >> 8; - ctrl->aal5_trailer [3] = skb->len; - - crc = crc32_be (~0, skb->data, skb->len); - for (i = 0; i < zero_padding; i++) - crc = crc32_be (crc, &zero, 1); - crc = crc32_be (crc, ctrl->aal5_trailer, 4); - crc = ~crc; - - ctrl->aal5_trailer [4] = crc >> 24; - ctrl->aal5_trailer [5] = crc >> 16; - ctrl->aal5_trailer [6] = crc >> 8; - ctrl->aal5_trailer [7] = crc; -} - -unsigned int udsl_write_cells (unsigned int howmany, struct sk_buff *skb, unsigned char **target_p) { - struct udsl_control *ctrl = UDSL_SKB (skb); - unsigned char *target = *target_p; - unsigned int nc, ne, i; - - dbg ("udsl_write_cells: howmany=%u, skb->len=%d, num_cells=%u, num_entire=%u, pdu_padding=%u", howmany, skb->len, ctrl->num_cells, ctrl->num_entire, ctrl->pdu_padding); - - nc = ctrl->num_cells; - ne = min (howmany, ctrl->num_entire); - - for (i = 0; i < ne; i++) { - memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); - target += ATM_CELL_HEADER; - memcpy (target, skb->data, ATM_CELL_PAYLOAD); - target += ATM_CELL_PAYLOAD; - __skb_pull (skb, ATM_CELL_PAYLOAD); - } - - ctrl->num_entire -= ne; - - if (!(ctrl->num_cells -= ne) || !(howmany -= ne)) - goto out; - - memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); - target += ATM_CELL_HEADER; - memcpy (target, skb->data, skb->len); - target += skb->len; - __skb_pull (skb, skb->len); - memset (target, 0, ctrl->pdu_padding); - target += ctrl->pdu_padding; - - if (--ctrl->num_cells) { - if (!--howmany) { - ctrl->pdu_padding = ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; - goto out; - } - - memcpy (target, ctrl->cell_header, ATM_CELL_HEADER); - target += ATM_CELL_HEADER; - memset (target, 0, ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER); - target += ATM_CELL_PAYLOAD - ATM_AAL5_TRAILER; - - if (--ctrl->num_cells) - BUG(); - } - - memcpy (target, ctrl->aal5_trailer, ATM_AAL5_TRAILER); - target += ATM_AAL5_TRAILER; - /* set pti bit in last cell */ - *(target + 3 - ATM_CELL_SIZE) |= 0x2; - -out: - *target_p = target; - return nc - ctrl->num_cells; -} - - -/************** -** receive ** -**************/ - -static void udsl_complete_receive (struct urb *urb, struct pt_regs *regs) -{ - struct udsl_instance_data *instance; - struct udsl_receiver *rcv; - unsigned long flags; - - if (!urb || !(rcv = urb->context) || !(instance = rcv->instance)) { - dbg ("udsl_complete_receive: bad urb!"); - return; - } - - dbg ("udsl_complete_receive entered (urb 0x%p, status %d)", urb, urb->status); - - /* may not be in_interrupt() */ - spin_lock_irqsave (&instance->completed_receivers_lock, flags); - list_add_tail (&rcv->list, &instance->completed_receivers); - tasklet_schedule (&instance->receive_tasklet); - spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); -} - -static void udsl_process_receive (unsigned long data) -{ - struct udsl_instance_data *instance = (struct udsl_instance_data *) data; - struct udsl_receiver *rcv; - unsigned long flags; - unsigned char *data_start; - struct sk_buff *skb; - struct urb *urb; - struct atmsar_vcc_data *atmsar_vcc = NULL; - struct sk_buff *new = NULL, *tmp = NULL; - int err; - - dbg ("udsl_process_receive entered"); - - spin_lock_irqsave (&instance->completed_receivers_lock, flags); - while (!list_empty (&instance->completed_receivers)) { - rcv = list_entry (instance->completed_receivers.next, struct udsl_receiver, list); - list_del (&rcv->list); - spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); - - urb = rcv->urb; - dbg ("udsl_process_receive: got packet %p with length %d and status %d", urb, urb->actual_length, urb->status); - - switch (urb->status) { - case 0: - dbg ("udsl_process_receive: processing urb with rcv %p, urb %p, skb %p", rcv, urb, rcv->skb); - - /* update the skb structure */ - skb = rcv->skb; - skb_trim (skb, 0); - skb_put (skb, urb->actual_length); - data_start = skb->data; - - dbg ("skb->len = %d", skb->len); - PACKETDEBUG (skb->data, skb->len); - - while ((new = - atmsar_decode_rawcell (instance->atmsar_vcc_list, skb, - &atmsar_vcc)) != NULL) { - dbg ("(after cell processing)skb->len = %d", new->len); - - switch (atmsar_vcc->type) { - case ATMSAR_TYPE_AAL5: - tmp = new; - new = atmsar_decode_aal5 (atmsar_vcc, new); - - /* we can't send NULL skbs upstream, the ATM layer would try to close the vcc... */ - if (new) { - dbg ("(after aal5 decap) skb->len = %d", new->len); - if (new->len && atm_charge (atmsar_vcc->vcc, new->truesize)) { - PACKETDEBUG (new->data, new->len); - atmsar_vcc->vcc->push (atmsar_vcc->vcc, new); - } else { - dbg - ("dropping incoming packet : rx_inuse = %d, vcc->sk->rcvbuf = %d, skb->true_size = %d", - atomic_read (&atmsar_vcc->vcc->rx_inuse), - atmsar_vcc->vcc->sk->rcvbuf, new->truesize); - dev_kfree_skb (new); - } - } else { - dbg ("atmsar_decode_aal5 returned NULL!"); - dev_kfree_skb (tmp); - } - break; - default: - /* not supported. we delete the skb. */ - printk (KERN_INFO - "SpeedTouch USB: illegal vcc type. Dropping packet.\n"); - dev_kfree_skb (new); - break; - } - } - - /* restore skb */ - skb_push (skb, skb->data - data_start); - - usb_fill_bulk_urb (urb, - instance->usb_dev, - usb_rcvbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_IN), - (unsigned char *) rcv->skb->data, - UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE, - udsl_complete_receive, - rcv); - if (!(err = usb_submit_urb (urb, GFP_ATOMIC))) - break; - dbg ("udsl_process_receive: submission failed (%d)", err); - /* fall through */ - default: /* error or urb unlinked */ - dbg ("udsl_process_receive: adding to spare_receivers"); - spin_lock_irqsave (&instance->spare_receivers_lock, flags); - list_add (&rcv->list, &instance->spare_receivers); - spin_unlock_irqrestore (&instance->spare_receivers_lock, flags); - break; - } /* switch */ - - spin_lock_irqsave (&instance->completed_receivers_lock, flags); - } /* while */ - spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); - dbg ("udsl_process_receive successful"); -} - -static void udsl_fire_receivers (struct udsl_instance_data *instance) -{ - struct list_head receivers, *pos, *n; - unsigned long flags; - - INIT_LIST_HEAD (&receivers); - - down (&instance->serialize); - - spin_lock_irqsave (&instance->spare_receivers_lock, flags); - list_splice_init (&instance->spare_receivers, &receivers); - spin_unlock_irqrestore (&instance->spare_receivers_lock, flags); - - list_for_each_safe (pos, n, &receivers) { - struct udsl_receiver *rcv = list_entry (pos, struct udsl_receiver, list); - - dbg ("udsl_fire_receivers: firing urb %p", rcv->urb); - - usb_fill_bulk_urb (rcv->urb, - instance->usb_dev, - usb_rcvbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_IN), - (unsigned char *) rcv->skb->data, - UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE, - udsl_complete_receive, - rcv); - - if (usb_submit_urb (rcv->urb, GFP_KERNEL) < 0) { - dbg ("udsl_fire_receivers: submit failed!"); - spin_lock_irqsave (&instance->spare_receivers_lock, flags); - list_move (pos, &instance->spare_receivers); - spin_unlock_irqrestore (&instance->spare_receivers_lock, flags); - } - } - - up (&instance->serialize); -} - - -/*********** -** send ** -***********/ - -static void udsl_complete_send (struct urb *urb, struct pt_regs *regs) -{ - struct udsl_instance_data *instance; - struct udsl_sender *snd; - unsigned long flags; - - if (!urb || !(snd = urb->context) || !(instance = snd->instance)) { - dbg ("udsl_complete_send: bad urb!"); - return; - } - - dbg ("udsl_complete_send entered (urb 0x%p, status %d)", urb, urb->status); - - /* may not be in_interrupt() */ - spin_lock_irqsave (&instance->send_lock, flags); - list_add (&snd->list, &instance->spare_senders); - list_add (&snd->buffer->list, &instance->spare_buffers); - tasklet_schedule (&instance->send_tasklet); - spin_unlock_irqrestore (&instance->send_lock, flags); -} - -static void udsl_process_send (unsigned long data) -{ - struct udsl_send_buffer *buf; - int err; - unsigned long flags; - struct udsl_instance_data *instance = (struct udsl_instance_data *) data; - unsigned int num_written; - struct sk_buff *skb; - struct udsl_sender *snd; - - dbg ("udsl_process_send entered"); - -made_progress: - spin_lock_irqsave (&instance->send_lock, flags); - while (!list_empty (&instance->spare_senders)) { - if (!list_empty (&instance->filled_buffers)) { - buf = list_entry (instance->filled_buffers.next, struct udsl_send_buffer, list); - list_del (&buf->list); - dbg ("sending filled buffer (0x%p)", buf); - } else if ((buf = instance->current_buffer)) { - instance->current_buffer = NULL; - dbg ("sending current buffer (0x%p)", buf); - } else /* all buffers empty */ - break; - - snd = list_entry (instance->spare_senders.next, struct udsl_sender, list); - list_del (&snd->list); - spin_unlock_irqrestore (&instance->send_lock, flags); - - snd->buffer = buf; - usb_fill_bulk_urb (snd->urb, - instance->usb_dev, - usb_sndbulkpipe (instance->usb_dev, UDSL_ENDPOINT_DATA_OUT), - buf->base, - (UDSL_SND_BUFFER_SIZE - buf->free_cells) * ATM_CELL_SIZE, - udsl_complete_send, - snd); - - dbg ("submitting urb 0x%p, contains %d cells", snd->urb, UDSL_SND_BUFFER_SIZE - buf->free_cells); - - if ((err = usb_submit_urb(snd->urb, GFP_ATOMIC)) < 0) { - dbg ("submission failed (%d)!", err); - spin_lock_irqsave (&instance->send_lock, flags); - list_add (&snd->list, &instance->spare_senders); - spin_unlock_irqrestore (&instance->send_lock, flags); - list_add (&buf->list, &instance->filled_buffers); - return; - } - - spin_lock_irqsave (&instance->send_lock, flags); - } /* while */ - spin_unlock_irqrestore (&instance->send_lock, flags); - - if (!instance->current_skb && !(instance->current_skb = skb_dequeue (&instance->sndqueue))) { - dbg ("done - no more skbs"); - return; - } - - skb = instance->current_skb; - - if (!(buf = instance->current_buffer)) { - spin_lock_irqsave (&instance->send_lock, flags); - if (list_empty (&instance->spare_buffers)) { - instance->current_buffer = NULL; - spin_unlock_irqrestore (&instance->send_lock, flags); - dbg ("done - no more buffers"); - return; - } - buf = list_entry (instance->spare_buffers.next, struct udsl_send_buffer, list); - list_del (&buf->list); - spin_unlock_irqrestore (&instance->send_lock, flags); - - buf->free_start = buf->base; - buf->free_cells = UDSL_SND_BUFFER_SIZE; - - instance->current_buffer = buf; - } - - num_written = udsl_write_cells (buf->free_cells, skb, &buf->free_start); - - dbg ("wrote %u cells from skb 0x%p to buffer 0x%p", num_written, skb, buf); - - if (!(buf->free_cells -= num_written)) { - list_add_tail (&buf->list, &instance->filled_buffers); - instance->current_buffer = NULL; - dbg ("queued filled buffer"); - } - - dbg ("buffer contains %d cells, %d left", UDSL_SND_BUFFER_SIZE - buf->free_cells, buf->free_cells); - - if (!UDSL_SKB (skb)->num_cells) { - struct atm_vcc *vcc = UDSL_SKB (skb)->atm_data.vcc; - - dbg ("discarding empty skb"); - if (vcc->pop) - vcc->pop (vcc, skb); - else - kfree_skb (skb); - instance->current_skb = NULL; - - if (vcc->stats) - atomic_inc (&vcc->stats->tx); - } - - goto made_progress; -} - -static void udsl_cancel_send (struct udsl_instance_data *instance, struct atm_vcc *vcc) -{ - unsigned long flags; - struct sk_buff *skb, *n; - - dbg ("udsl_cancel_send entered"); - spin_lock_irqsave (&instance->sndqueue.lock, flags); - for (skb = instance->sndqueue.next, n = skb->next; skb != (struct sk_buff *)&instance->sndqueue; skb = n, n = skb->next) - if (UDSL_SKB (skb)->atm_data.vcc == vcc) { - dbg ("popping skb 0x%p", skb); - __skb_unlink (skb, &instance->sndqueue); - if (vcc->pop) - vcc->pop (vcc, skb); - else - kfree_skb (skb); - } - spin_unlock_irqrestore (&instance->sndqueue.lock, flags); - - tasklet_disable (&instance->send_tasklet); - if ((skb = instance->current_skb) && (UDSL_SKB (skb)->atm_data.vcc == vcc)) { - dbg ("popping current skb (0x%p)", skb); - instance->current_skb = NULL; - if (vcc->pop) - vcc->pop (vcc, skb); - else - kfree_skb (skb); - } - tasklet_enable (&instance->send_tasklet); - dbg ("udsl_cancel_send done"); -} - -static int udsl_atm_send (struct atm_vcc *vcc, struct sk_buff *skb) -{ - struct udsl_instance_data *instance = vcc->dev->dev_data; - - dbg ("udsl_atm_send called (skb 0x%p, len %u)", skb, skb->len); - - if (!instance || !instance->usb_dev) { - dbg ("NULL data!"); - return -ENODEV; - } - - if (!instance->firmware_loaded) - return -EAGAIN; - - if (vcc->qos.aal != ATM_AAL5) { - dbg ("unsupported ATM type %d!", vcc->qos.aal); - return -EINVAL; - } - - if (skb->len > ATM_MAX_AAL5_PDU) { - dbg ("packet too long (%d vs %d)!", skb->len, ATM_MAX_AAL5_PDU); - return -EINVAL; - } - - PACKETDEBUG (skb->data, skb->len); - - udsl_groom_skb (vcc, skb); - skb_queue_tail (&instance->sndqueue, skb); - tasklet_schedule (&instance->send_tasklet); - - return 0; -} - - -/********** -** ATM ** -**********/ - -static void udsl_atm_dev_close (struct atm_dev *dev) -{ - struct udsl_instance_data *instance = dev->dev_data; - - if (!instance) { - dbg ("udsl_atm_dev_close: NULL instance!"); - return; - } - - dbg ("udsl_atm_dev_close: queue has %u elements", instance->sndqueue.qlen); - - dbg ("udsl_atm_dev_close: killing tasklet"); - tasklet_kill (&instance->send_tasklet); - dbg ("udsl_atm_dev_close: freeing instance"); - kfree (instance); - dev->dev_data = NULL; -} - -static int udsl_atm_proc_read (struct atm_dev *atm_dev, loff_t *pos, char *page) -{ - struct udsl_instance_data *instance = atm_dev->dev_data; - int left = *pos; - - if (!instance) { - dbg ("NULL instance!"); - return -ENODEV; - } - - if (!left--) - return sprintf (page, "%s\n", instance->description); - - if (!left--) - return sprintf (page, "MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", - atm_dev->esi[0], atm_dev->esi[1], atm_dev->esi[2], - atm_dev->esi[3], atm_dev->esi[4], atm_dev->esi[5]); - - if (!left--) - return sprintf (page, "AAL5: tx %d ( %d err ), rx %d ( %d err, %d drop )\n", - atomic_read (&atm_dev->stats.aal5.tx), - atomic_read (&atm_dev->stats.aal5.tx_err), - atomic_read (&atm_dev->stats.aal5.rx), - atomic_read (&atm_dev->stats.aal5.rx_err), - atomic_read (&atm_dev->stats.aal5.rx_drop)); - - if (!left--) { - switch (atm_dev->signal) { - case ATM_PHY_SIG_FOUND: - sprintf (page, "Line up"); - break; - case ATM_PHY_SIG_LOST: - sprintf (page, "Line down"); - break; - default: - sprintf (page, "Line state unknown"); - break; - } - - if (instance->usb_dev) { - if (!instance->firmware_loaded) - strcat (page, ", no firmware\n"); - else - strcat (page, ", firmware loaded\n"); - } else - strcat (page, ", disconnected\n"); - - return strlen (page); - } - - return 0; -} - -static int udsl_atm_open (struct atm_vcc *vcc, short vpi, int vci) -{ - struct udsl_instance_data *instance = vcc->dev->dev_data; - - dbg ("udsl_atm_open called"); - - if (!instance || !instance->usb_dev) { - dbg ("NULL data!"); - return -ENODEV; - } - - /* at the moment only AAL5 support */ - if (vcc->qos.aal != ATM_AAL5) - return -EINVAL; - - MOD_INC_USE_COUNT; - - vcc->dev_data = - atmsar_open (&(instance->atmsar_vcc_list), vcc, ATMSAR_TYPE_AAL5, vpi, vci, 0, 0, - ATMSAR_USE_53BYTE_CELL | ATMSAR_SET_PTI); - if (!vcc->dev_data) { - MOD_DEC_USE_COUNT; - return -ENOMEM; /* this is the only reason atmsar_open can fail... */ - } - - vcc->vpi = vpi; - vcc->vci = vci; - set_bit (ATM_VF_ADDR, &vcc->flags); - set_bit (ATM_VF_PARTIAL, &vcc->flags); - set_bit (ATM_VF_READY, &vcc->flags); - - ((struct atmsar_vcc_data *)vcc->dev_data)->mtu = UDSL_MAX_AAL5_MRU; - - if (instance->firmware_loaded) - udsl_fire_receivers (instance); - - dbg ("udsl_atm_open successful"); - return 0; -} - -static void udsl_atm_close (struct atm_vcc *vcc) -{ - struct udsl_instance_data *instance = vcc->dev->dev_data; - - dbg ("udsl_atm_close called"); - - if (!instance) { - dbg ("NULL instance!"); - return; - } - - /* freeing resources */ - /* cancel all sends on this vcc */ - udsl_cancel_send (instance, vcc); - - atmsar_close (&(instance->atmsar_vcc_list), vcc->dev_data); - vcc->dev_data = NULL; - clear_bit (ATM_VF_PARTIAL, &vcc->flags); - - /* freeing address */ - vcc->vpi = ATM_VPI_UNSPEC; - vcc->vci = ATM_VCI_UNSPEC; - clear_bit (ATM_VF_ADDR, &vcc->flags); - - MOD_DEC_USE_COUNT; - - dbg ("udsl_atm_close successful"); - return; -} - -static int udsl_atm_ioctl (struct atm_dev *dev, unsigned int cmd, void *arg) -{ - switch (cmd) { - case ATM_QUERYLOOP: - return put_user (ATM_LM_NONE, (int *) arg) ? -EFAULT : 0; - default: - return -ENOIOCTLCMD; - } -} - - -/********** -** USB ** -**********/ - -static int udsl_usb_ioctl (struct usb_interface *intf, unsigned int code, void *user_data) -{ - struct udsl_instance_data *instance = usb_get_intfdata (intf); - - dbg ("udsl_usb_ioctl entered"); - - if (!instance) { - dbg ("NULL instance!"); - return -ENODEV; - } - - switch (code) { - case UDSL_IOCTL_START: - instance->atm_dev->signal = ATM_PHY_SIG_FOUND; - down (&instance->serialize); /* vs self */ - if (!instance->firmware_loaded) { - usb_set_interface (instance->usb_dev, 1, 1); - instance->firmware_loaded = 1; - } - up (&instance->serialize); - udsl_fire_receivers (instance); - return 0; - case UDSL_IOCTL_STOP: - instance->atm_dev->signal = ATM_PHY_SIG_LOST; - return 0; - default: - return -ENOTTY; - } -} - -static int udsl_usb_probe (struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - int ifnum = intf->altsetting->desc.bInterfaceNumber; - struct udsl_instance_data *instance; - unsigned char mac_str [13]; - int i, length; - char *buf; - - dbg ("Trying device with Vendor=0x%x, Product=0x%x, ifnum %d", - dev->descriptor.idVendor, dev->descriptor.idProduct, ifnum); - - if ((dev->descriptor.bDeviceClass != USB_CLASS_VENDOR_SPEC) || - (dev->descriptor.idVendor != SPEEDTOUCH_VENDORID) || - (dev->descriptor.idProduct != SPEEDTOUCH_PRODUCTID) || (ifnum != 1)) - return -ENODEV; - - dbg ("Device Accepted"); - - /* instance init */ - if (!(instance = kmalloc (sizeof (struct udsl_instance_data), GFP_KERNEL))) { - dbg ("No memory for Instance data!"); - return -ENOMEM; - } - - memset (instance, 0, sizeof (struct udsl_instance_data)); - - init_MUTEX (&instance->serialize); - - instance->usb_dev = dev; - - spin_lock_init (&instance->spare_receivers_lock); - INIT_LIST_HEAD (&instance->spare_receivers); - - spin_lock_init (&instance->completed_receivers_lock); - INIT_LIST_HEAD (&instance->completed_receivers); - - tasklet_init (&instance->receive_tasklet, udsl_process_receive, (unsigned long) instance); - - skb_queue_head_init (&instance->sndqueue); - - spin_lock_init (&instance->send_lock); - INIT_LIST_HEAD (&instance->spare_senders); - INIT_LIST_HEAD (&instance->spare_buffers); - - tasklet_init (&instance->send_tasklet, udsl_process_send, (unsigned long) instance); - INIT_LIST_HEAD (&instance->filled_buffers); - - /* receive init */ - for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { - struct udsl_receiver *rcv = &(instance->all_receivers[i]); - - if (!(rcv->skb = dev_alloc_skb (UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE))) { - dbg ("No memory for skb %d!", i); - goto fail; - } - - if (!(rcv->urb = usb_alloc_urb (0, GFP_KERNEL))) { - dbg ("No memory for receive urb %d!", i); - goto fail; - } - - rcv->instance = instance; - - list_add (&rcv->list, &instance->spare_receivers); - - dbg ("skb->truesize = %d (asked for %d)", rcv->skb->truesize, UDSL_RCV_BUFFER_SIZE * ATM_CELL_SIZE); - } - - /* send init */ - for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) { - struct udsl_sender *snd = &(instance->all_senders[i]); - - if (!(snd->urb = usb_alloc_urb (0, GFP_KERNEL))) { - dbg ("No memory for send urb %d!", i); - goto fail; - } - - snd->instance = instance; - - list_add (&snd->list, &instance->spare_senders); - } - - for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) { - struct udsl_send_buffer *buf = &(instance->all_buffers[i]); - - if (!(buf->base = kmalloc (UDSL_SND_BUFFER_SIZE * ATM_CELL_SIZE, GFP_KERNEL))) { - dbg ("No memory for send buffer %d!", i); - goto fail; - } - - list_add (&buf->list, &instance->spare_buffers); - } - - /* atm init */ - if (!(instance->atm_dev = atm_dev_register (udsl_driver_name, &udsl_atm_devops, -1, 0))) { - dbg ("failed to register ATM device!"); - goto fail; - } - - instance->atm_dev->ci_range.vpi_bits = ATM_CI_MAX; - instance->atm_dev->ci_range.vci_bits = ATM_CI_MAX; - instance->atm_dev->signal = ATM_PHY_SIG_UNKNOWN; - - /* tmp init atm device, set to 128kbit */ - instance->atm_dev->link_rate = 128 * 1000 / 424; - - /* set MAC address, it is stored in the serial number */ - memset (instance->atm_dev->esi, 0, sizeof (instance->atm_dev->esi)); - if (usb_string (dev, dev->descriptor.iSerialNumber, mac_str, sizeof (mac_str)) == 12) - for (i = 0; i < 6; i++) - instance->atm_dev->esi[i] = (hex2int (mac_str[i * 2]) * 16) + (hex2int (mac_str[i * 2 + 1])); - - /* device description */ - buf = instance->description; - length = sizeof (instance->description); - - if ((i = usb_string (dev, dev->descriptor.iProduct, buf, length)) < 0) - goto finish; - - buf += i; - length -= i; - - i = snprintf (buf, length, " ("); - buf += i; - length -= i; - - if (length <= 0 || (i = usb_make_path (dev, buf, length)) < 0) - goto finish; - - buf += i; - length -= i; - - snprintf (buf, length, ")"); - -finish: - /* ready for ATM callbacks */ - instance->atm_dev->dev_data = instance; - - usb_set_intfdata (intf, instance); - - return 0; - -fail: - for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) - kfree (instance->all_buffers[i].base); - - for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) - usb_free_urb (instance->all_senders[i].urb); - - for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { - struct udsl_receiver *rcv = &(instance->all_receivers[i]); - - usb_free_urb (rcv->urb); - - if (rcv->skb) - kfree_skb (rcv->skb); - } - - kfree (instance); - - return -ENOMEM; -} - -static void udsl_usb_disconnect (struct usb_interface *intf) -{ - struct udsl_instance_data *instance = usb_get_intfdata (intf); - struct list_head *pos; - unsigned long flags; - unsigned int count = 0; - int result, i; - - dbg ("disconnecting"); - - usb_set_intfdata (intf, NULL); - - if (!instance) { - dbg ("NULL instance!"); - return; - } - - tasklet_disable (&instance->receive_tasklet); - - /* receive finalize */ - down (&instance->serialize); /* vs udsl_fire_receivers */ - /* no need to take the spinlock */ - list_for_each (pos, &instance->spare_receivers) - if (++count > UDSL_NUMBER_RCV_URBS) - panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); - INIT_LIST_HEAD (&instance->spare_receivers); - up (&instance->serialize); - - dbg ("udsl_usb_disconnect: flushed %u spare receivers", count); - - count = UDSL_NUMBER_RCV_URBS - count; - - for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) - if ((result = usb_unlink_urb (instance->all_receivers[i].urb)) < 0) - dbg ("udsl_usb_disconnect: usb_unlink_urb on receive urb %d returned %d", i, result); - - /* wait for completion handlers to finish */ - do { - unsigned int completed = 0; - - spin_lock_irqsave (&instance->completed_receivers_lock, flags); - list_for_each (pos, &instance->completed_receivers) - if (++completed > count) - panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); - spin_unlock_irqrestore (&instance->completed_receivers_lock, flags); - - dbg ("udsl_usb_disconnect: found %u completed receivers", completed); - - if (completed == count) - break; - - yield (); - } while (1); - - dbg ("udsl_usb_disconnect: flushing"); - /* no need to take the spinlock */ - INIT_LIST_HEAD (&instance->completed_receivers); - - tasklet_enable (&instance->receive_tasklet); - tasklet_kill (&instance->receive_tasklet); - - dbg ("udsl_usb_disconnect: freeing receivers"); - for (i = 0; i < UDSL_NUMBER_RCV_URBS; i++) { - struct udsl_receiver *rcv = &(instance->all_receivers[i]); - - usb_free_urb (rcv->urb); - kfree_skb (rcv->skb); - } - - /* send finalize */ - tasklet_disable (&instance->send_tasklet); - - for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) - if ((result = usb_unlink_urb (instance->all_senders[i].urb)) < 0) - dbg ("udsl_usb_disconnect: usb_unlink_urb on send urb %d returned %d", i, result); - - /* wait for completion handlers to finish */ - do { - count = 0; - spin_lock_irqsave (&instance->send_lock, flags); - list_for_each (pos, &instance->spare_senders) - if (++count > UDSL_NUMBER_SND_URBS) - panic (__FILE__ ": memory corruption detected at line %d!\n", __LINE__); - spin_unlock_irqrestore (&instance->send_lock, flags); - - dbg ("udsl_usb_disconnect: found %u spare senders", count); - - if (count == UDSL_NUMBER_SND_URBS) - break; - - yield (); - } while (1); - - dbg ("udsl_usb_disconnect: flushing"); - /* no need to take the spinlock */ - INIT_LIST_HEAD (&instance->spare_senders); - INIT_LIST_HEAD (&instance->spare_buffers); - instance->current_buffer = NULL; - - tasklet_enable (&instance->send_tasklet); - - dbg ("udsl_usb_disconnect: freeing senders"); - for (i = 0; i < UDSL_NUMBER_SND_URBS; i++) - usb_free_urb (instance->all_senders[i].urb); - - dbg ("udsl_usb_disconnect: freeing buffers"); - for (i = 0; i < UDSL_NUMBER_SND_BUFS; i++) - kfree (instance->all_buffers[i].base); - - instance->usb_dev = NULL; - - /* atm finalize */ - shutdown_atm_dev (instance->atm_dev); /* frees instance */ -} - - -/*********** -** init ** -***********/ - -static int __init udsl_usb_init (void) -{ - struct sk_buff *skb; /* dummy for sizeof */ - - dbg ("udsl_usb_init: driver version " DRIVER_VERSION); - - if (sizeof (struct udsl_control) > sizeof (skb->cb)) { - printk (KERN_ERR __FILE__ ": unusable with this kernel!\n"); - return -EIO; - } - - return usb_register (&udsl_usb_driver); -} - -static void __exit udsl_usb_cleanup (void) -{ - dbg ("udsl_usb_cleanup"); - - usb_deregister (&udsl_usb_driver); -} - -module_init (udsl_usb_init); -module_exit (udsl_usb_cleanup); - -MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_DESCRIPTION (DRIVER_DESC); -MODULE_LICENSE ("GPL"); - - -/************ -** debug ** -************/ - -#ifdef DEBUG_PACKET -static int udsl_print_packet (const unsigned char *data, int len) -{ - unsigned char buffer [256]; - int i = 0, j = 0; - - for (i = 0; i < len;) { - buffer[0] = '\0'; - sprintf (buffer, "%.3d :", i); - for (j = 0; (j < 16) && (i < len); j++, i++) { - sprintf (buffer, "%s %2.2x", buffer, data[i]); - } - dbg ("%s", buffer); - } - return i; -} -#endif -- cgit v1.2.3 From 18e7e540b936fe652c6875219f64eb14514eba7f Mon Sep 17 00:00:00 2001 From: Steven Cole Date: Tue, 18 Mar 2003 19:29:45 -0800 Subject: [PATCH] i2c: spelling corrections for drivers/i2c Here are some spelling and typo fixes for drivers/i2c. --- drivers/i2c/chips/adm1021.c | 4 ++-- drivers/i2c/chips/lm75.c | 2 +- drivers/i2c/i2c-algo-pcf.c | 6 +++--- drivers/i2c/i2c-proc.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c index 5c15c7b4be1f..c4370afc01e1 100644 --- a/drivers/i2c/chips/adm1021.c +++ b/drivers/i2c/chips/adm1021.c @@ -93,9 +93,9 @@ SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1 /* Initial values */ -/* Note: Eventhough I left the low and high limits named os and hyst, +/* Note: Even though I left the low and high limits named os and hyst, they don't quite work like a thermostat the way the LM75 does. I.e., -a lower temp than THYST actuall triggers an alarm instead of +a lower temp than THYST actually triggers an alarm instead of clearing it. Weird, ey? --Phil */ #define adm1021_INIT_TOS 60 #define adm1021_INIT_THYST 20 diff --git a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c index e625528e7b3a..da1e4d2c2c28 100644 --- a/drivers/i2c/chips/lm75.c +++ b/drivers/i2c/chips/lm75.c @@ -25,7 +25,7 @@ #include -#define LM75_SYSCTL_TEMP 1200 /* Degrees Celcius * 10 */ +#define LM75_SYSCTL_TEMP 1200 /* Degrees Celsius * 10 */ /* Addresses to scan */ static unsigned short normal_i2c[] = { SENSORS_I2C_END }; diff --git a/drivers/i2c/i2c-algo-pcf.c b/drivers/i2c/i2c-algo-pcf.c index 874d37827954..c7383b281a34 100644 --- a/drivers/i2c/i2c-algo-pcf.c +++ b/drivers/i2c/i2c-algo-pcf.c @@ -152,7 +152,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) /* load own address in S0, effective address is (own << 1) */ i2c_outb(adap, get_own(adap)); - /* check it's realy writen */ + /* check it's really written */ if ((temp = i2c_inb(adap)) != get_own(adap)) { DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S0 (0x%02x).\n", temp)); return -ENXIO; @@ -168,7 +168,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) /* load clock register S2 */ i2c_outb(adap, get_clock(adap)); - /* check it's realy writen, the only 5 lowest bits does matter */ + /* check it's really written, the only 5 lowest bits does matter */ if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) { DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S2 (0x%02x).\n", temp)); return -ENXIO; @@ -177,7 +177,7 @@ static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) /* Enable serial interface, idle, S0 selected */ set_pcf(adap, 1, I2C_PCF_IDLE); - /* check to see PCF is realy idled and we can access status register */ + /* check to see PCF is really idled and we can access status register */ if ((temp = get_pcf(adap, 1)) != (I2C_PCF_PIN | I2C_PCF_BB)) { DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp)); return -ENXIO; diff --git a/drivers/i2c/i2c-proc.c b/drivers/i2c/i2c-proc.c index 73bb33815907..313b5b5c4d7c 100644 --- a/drivers/i2c/i2c-proc.c +++ b/drivers/i2c/i2c-proc.c @@ -270,7 +270,7 @@ static int i2c_sysctl_chips(ctl_table * table, int *name, int nlen, } -/* This funcion reads or writes a 'real' value (encoded by the combination +/* This function reads or writes a 'real' value (encoded by the combination of an integer and a magnitude, the last is the power of ten the value should be divided with) to a /proc/sys directory. To use this function, you must (before registering the ctl_table) set the extra2 field to the -- cgit v1.2.3 From 1bee5616f6c9167ff8c657f37ec6a1101e9e8214 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 18 Mar 2003 21:09:22 -0800 Subject: [PATCH] USB: ehci-hcd, prink tweaks A not-very interesting patch, it just cleans up some debug output. --- drivers/usb/host/ehci-dbg.c | 6 +++--- drivers/usb/host/ehci-hcd.c | 15 ++++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index 4e57b88d616d..32478229d4c9 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -117,10 +117,10 @@ static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} static void __attribute__((__unused__)) dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) { - dbg ("%s %p info1 %x info2 %x hw_curr %x qtd_next %x", label, - qh, qh->hw_info1, qh->hw_info2, + dbg ("%s %p n%08x info1 %x info2 %x hw_curr %x qtd_next %x", label, + qh, qh->hw_next, qh->hw_info1, qh->hw_info2, qh->hw_current, qh->hw_qtd_next); - dbg (" alt+errs= %x, token= %x, page0= %x, page1= %x", + dbg (" alt+nak+t= %x, token= %x, page0= %x, page1= %x", qh->hw_alt_next, qh->hw_token, qh->hw_buf [0], qh->hw_buf [1]); if (qh->hw_buf [2]) { diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index d0954475b709..072d70416540 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -576,7 +576,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state) int ports; int i; - dbg ("%s: suspend to %d", hcd_to_bus (hcd)->bus_name, state); + ehci_dbg (ehci, "suspend to %d\n", state); ports = HCS_N_PORTS (ehci->hcs_params); @@ -593,7 +593,7 @@ static int ehci_suspend (struct usb_hcd *hcd, u32 state) if ((temp & PORT_PE) == 0 || (temp & PORT_OWNER) != 0) continue; -dbg ("%s: suspend port %d", hcd_to_bus (hcd)->bus_name, i); + ehci_dbg (ehci, "suspend port %d", i); temp |= PORT_SUSPEND; writel (temp, &ehci->regs->port_status [i]); } @@ -615,7 +615,7 @@ static int ehci_resume (struct usb_hcd *hcd) int ports; int i; - dbg ("%s: resume", hcd_to_bus (hcd)->bus_name); + ehci_dbg (ehci, "resume\n"); ports = HCS_N_PORTS (ehci->hcs_params); @@ -635,7 +635,7 @@ static int ehci_resume (struct usb_hcd *hcd) if ((temp & PORT_PE) == 0 || (temp & PORT_SUSPEND) != 0) continue; -dbg ("%s: resume port %d", hcd_to_bus (hcd)->bus_name, i); + ehci_dbg (ehci, "resume port %d", i); temp |= PORT_RESUME; writel (temp, &ehci->regs->port_status [i]); readl (&ehci->regs->command); /* unblock posted writes */ @@ -880,8 +880,8 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev) /* ASSERT: no requests/urbs are still linked (so no TDs) */ /* ASSERT: nobody can be submitting urbs for this any more */ - dbg ("%s: free_config devnum %d", - hcd_to_bus (hcd)->bus_name, udev->devnum); + ehci_dbg (ehci, "free_config %s devnum %d\n", + udev->devpath, udev->devnum); spin_lock_irqsave (&ehci->lock, flags); for (i = 0; i < 32; i++) { @@ -912,7 +912,8 @@ static void ehci_free_config (struct usb_hcd *hcd, struct usb_device *udev) dev->ep [i] = 0; if (qh->qh_state == QH_STATE_IDLE) goto idle; - dbg ("free_config, async ep 0x%02x qh %p", i, qh); + ehci_dbg (ehci, "free_config, async ep 0x%02x qh %p", + i, qh); /* scan_async() empties the ring as it does its work, * using IAA, but doesn't (yet?) turn it off. if it -- cgit v1.2.3 From 401abfce5219e2597246be25ad1aabd5a16db55e Mon Sep 17 00:00:00 2001 From: Oleg Drokin Date: Tue, 18 Mar 2003 23:41:23 -0800 Subject: [PATCH] USB: Memleak in drivers/usb/hub.c::usb_reset_device Hello! On Fri, Mar 14, 2003 at 11:37:19AM -0800, Greg KH wrote: > > There seems to be a memleak in drivers/usb/hub.c::usb_reset_device() > > on error exit path. See the patch. > > Found with help of smatch + enhanced unfree script. > And yes, as David said, there is another kind of error in this area for > 2.5. Patches to clean that up would be appreciated. Ok, I guess something like that should work: --- drivers/usb/core/hub.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b8f282d5524a..03696016c495 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1175,7 +1175,7 @@ void usb_hub_cleanup(void) int usb_reset_device(struct usb_device *dev) { struct usb_device *parent = dev->parent; - struct usb_device_descriptor descriptor; + struct usb_device_descriptor *descriptor; int i, ret, port = -1; if (!parent) { @@ -1224,17 +1224,24 @@ int usb_reset_device(struct usb_device *dev) * If nothing changed, we reprogram the configuration and then * the alternate settings. */ - ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &descriptor, - sizeof(descriptor)); - if (ret < 0) + descriptor = kmalloc(sizeof *descriptor, GFP_NOIO); + if (!descriptor) { + return -ENOMEM; + } + ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, descriptor, + sizeof(*descriptor)); + if (ret < 0) { + kfree(descriptor); return ret; + } - le16_to_cpus(&descriptor.bcdUSB); - le16_to_cpus(&descriptor.idVendor); - le16_to_cpus(&descriptor.idProduct); - le16_to_cpus(&descriptor.bcdDevice); + le16_to_cpus(&descriptor->bcdUSB); + le16_to_cpus(&descriptor->idVendor); + le16_to_cpus(&descriptor->idProduct); + le16_to_cpus(&descriptor->bcdDevice); - if (memcmp(&dev->descriptor, &descriptor, sizeof(descriptor))) { + if (memcmp(&dev->descriptor, descriptor, sizeof(*descriptor))) { + kfree(descriptor); usb_destroy_configuration(dev); ret = usb_get_device_descriptor(dev); @@ -1268,6 +1275,8 @@ int usb_reset_device(struct usb_device *dev) return 1; } + kfree(descriptor); + ret = usb_set_configuration(dev, dev->actconfig->desc.bConfigurationValue); if (ret < 0) { err("failed to set dev %s active configuration (error=%d)", -- cgit v1.2.3 From 789657f65c9b48fdbc5083bf55aecef83cb3d5ff Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Tue, 18 Mar 2003 23:41:50 -0800 Subject: [PATCH] USB: reduce stack usage in cdc-ether This patch to 2.5.64 reduces the large stack usage in log_device_info() [and makes it static to boot]. --- drivers/usb/net/cdc-ether.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/cdc-ether.c b/drivers/usb/net/cdc-ether.c index 2dc8dfe0ba99..e6b530720209 100644 --- a/drivers/usb/net/cdc-ether.c +++ b/drivers/usb/net/cdc-ether.c @@ -1064,15 +1064,23 @@ static void set_ethernet_addr( ether_dev_t *ether_dev ) // Used by driver's probe routine //////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// -void log_device_info(ether_dev_t *ether_dev) +static void log_device_info(ether_dev_t *ether_dev) { int len; int string_num; - unsigned char manu[256]; - unsigned char prod[256]; - unsigned char sern[256]; + unsigned char *manu = NULL; + unsigned char *prod = NULL; + unsigned char *sern = NULL; unsigned char *mac_addr; + manu = kmalloc(256, GFP_KERNEL); + prod = kmalloc(256, GFP_KERNEL); + sern = kmalloc(256, GFP_KERNEL); + if (!manu || !prod || !sern) { + dbg("no mem for log_device_info"); + goto fini; + } + // Default empty strings in case we don't find a real one manu[0] = 0x00; prod[0] = 0x00; @@ -1113,6 +1121,10 @@ void log_device_info(ether_dev_t *ether_dev) ether_dev->net->name, manu, prod, sern, mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5] ); +fini: + kfree(manu); + kfree(prod); + kfree(sern); } /* Forward declaration */ -- cgit v1.2.3 From 951fe07ecc95fd056648ce221af76e6388939b5b Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 19 Mar 2003 05:17:20 -0800 Subject: [NET]: Kill NETIF_F_DYNALLOC, based upon ideas from Adam J. Richter --- drivers/net/ppp_generic.c | 7 ++++++- include/linux/netdevice.h | 1 - net/8021q/vlan.c | 1 - net/8021q/vlan_dev.c | 1 + net/core/dev.c | 6 ++---- net/core/dst.c | 2 +- net/ipv4/ip_gre.c | 2 +- net/ipv4/ipip.c | 2 +- net/ipv4/ipmr.c | 7 ++++++- net/ipv6/sit.c | 2 +- net/irda/irda_device.c | 8 ++++++-- net/irda/irlan/irlan_eth.c | 10 ---------- 12 files changed, 25 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index e5f5670201e1..e78c6e1006ae 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -2214,6 +2214,11 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) * and for initialization. */ +static void ppp_device_destructor(struct net_device *dev) +{ + kfree(dev); +} + /* * Create a new ppp interface unit. Fails if it can't allocate memory * or if there is already a unit with the requested number. @@ -2262,7 +2267,7 @@ ppp_create_interface(int unit, int *retp) dev->init = ppp_net_init; sprintf(dev->name, "ppp%d", unit); dev->priv = ppp; - dev->features |= NETIF_F_DYNALLOC; + dev->destructor = ppp_device_destructor; rtnl_lock(); ret = register_netdevice(dev); diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index bd93370ab0a7..d1f308ccb7c1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -365,7 +365,6 @@ struct net_device #define NETIF_F_IP_CSUM 2 /* Can checksum only TCP/UDP over IPv4. */ #define NETIF_F_NO_CSUM 4 /* Does not require checksum. F.e. loopack. */ #define NETIF_F_HW_CSUM 8 /* Can checksum all the packets. */ -#define NETIF_F_DYNALLOC 16 /* Self-dectructable device. */ #define NETIF_F_HIGHDMA 32 /* Can DMA to high memory. */ #define NETIF_F_FRAGLIST 64 /* Scatter/gather IO. */ #define NETIF_F_HW_VLAN_TX 128 /* Transmit VLAN hw acceleration */ diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 35f43fd81c22..25562366d4c0 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -433,7 +433,6 @@ static struct net_device *register_vlan_device(const char *eth_IF_name, /* set up method calls */ new_dev->init = vlan_dev_init; new_dev->destructor = vlan_dev_destruct; - new_dev->features |= NETIF_F_DYNALLOC ; /* new_dev->ifindex = 0; it will be set when added to * the global list. diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index b1751235dacd..907073996bc7 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -785,6 +785,7 @@ void vlan_dev_destruct(struct net_device *dev) kfree(dev->priv); dev->priv = NULL; } + kfree(dev); } } diff --git a/net/core/dev.c b/net/core/dev.c index 2c37c767663b..2d5ae21a98de 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2639,12 +2639,10 @@ int netdev_finish_unregister(struct net_device *dev) } #ifdef NET_REFCNT_DEBUG printk(KERN_DEBUG "netdev_finish_unregister: %s%s.\n", dev->name, - (dev->features & NETIF_F_DYNALLOC)?"":", old style"); + (dev->destructor != NULL)?"":", old style"); #endif if (dev->destructor) dev->destructor(dev); - if (dev->features & NETIF_F_DYNALLOC) - kfree(dev); return 0; } @@ -2724,7 +2722,7 @@ int unregister_netdevice(struct net_device *dev) free_divert_blk(dev); #endif - if (dev->features & NETIF_F_DYNALLOC) { + if (dev->destructor != NULL) { #ifdef NET_REFCNT_DEBUG if (atomic_read(&dev->refcnt) != 1) printk(KERN_DEBUG "unregister_netdevice: holding %s " diff --git a/net/core/dst.c b/net/core/dst.c index 2cde81a0ca7a..ea1b6f6751bd 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -228,7 +228,7 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void _race_ _condition_. */ if (event!=NETDEV_DOWN && - !(dev->features & NETIF_F_DYNALLOC) && + dev->destructor == NULL && dst->output == dst_blackhole) { dst->dev = &loopback_dev; dev_put(dev); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 8b89b84c90f1..375786d1f583 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -273,7 +273,6 @@ static struct ip_tunnel * ipgre_tunnel_locate(struct ip_tunnel_parm *parms, int nt = (struct ip_tunnel*)dev->priv; nt->dev = dev; dev->init = ipgre_tunnel_init; - dev->features |= NETIF_F_DYNALLOC; memcpy(&nt->parms, parms, sizeof(*parms)); nt->parms.name[IFNAMSIZ-1] = '\0'; strcpy(dev->name, nt->parms.name); @@ -305,6 +304,7 @@ failed: static void ipgre_tunnel_destructor(struct net_device *dev) { if (dev != &ipgre_fb_tunnel_dev) { + kfree(dev); MOD_DEC_USE_COUNT; } } diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 567c237a975b..d145db8137b5 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -242,7 +242,6 @@ struct ip_tunnel * ipip_tunnel_locate(struct ip_tunnel_parm *parms, int create) nt = (struct ip_tunnel*)dev->priv; nt->dev = dev; dev->init = ipip_tunnel_init; - dev->features |= NETIF_F_DYNALLOC; memcpy(&nt->parms, parms, sizeof(*parms)); nt->parms.name[IFNAMSIZ-1] = '\0'; strcpy(dev->name, nt->parms.name); @@ -274,6 +273,7 @@ failed: static void ipip_tunnel_destructor(struct net_device *dev) { if (dev != &ipip_fb_tunnel_dev) { + kfree(dev); MOD_DEC_USE_COUNT; } } diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 2dd886836e38..b6c5c1c872c4 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -182,6 +182,11 @@ static struct net_device_stats *reg_vif_get_stats(struct net_device *dev) return (struct net_device_stats*)dev->priv; } +static void vif_dev_destructor(struct net_device *dev) +{ + kfree(dev); +} + static struct net_device *ipmr_reg_vif(struct vifctl *v) { @@ -205,7 +210,7 @@ struct net_device *ipmr_reg_vif(struct vifctl *v) dev->flags = IFF_NOARP; dev->hard_start_xmit = reg_vif_xmit; dev->get_stats = reg_vif_get_stats; - dev->features |= NETIF_F_DYNALLOC; + dev->destructor = vif_dev_destructor; if (register_netdevice(dev)) { kfree(dev); diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 5a1230fdf8be..3b3490325222 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -181,7 +181,6 @@ static struct ip_tunnel * ipip6_tunnel_locate(struct ip_tunnel_parm *parms, int nt = (struct ip_tunnel*)dev->priv; nt->dev = dev; dev->init = ipip6_tunnel_init; - dev->features |= NETIF_F_DYNALLOC; memcpy(&nt->parms, parms, sizeof(*parms)); nt->parms.name[IFNAMSIZ-1] = '\0'; strcpy(dev->name, nt->parms.name); @@ -213,6 +212,7 @@ failed: static void ipip6_tunnel_destructor(struct net_device *dev) { if (dev != &ipip6_fb_tunnel_dev) { + kfree(dev); MOD_DEC_USE_COUNT; } } diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c index c7782f1774ad..aad0321c1469 100644 --- a/net/irda/irda_device.c +++ b/net/irda/irda_device.c @@ -372,6 +372,11 @@ static void irda_task_timer_expired(void *data) irda_task_kick(task); } +static void irda_device_destructor(struct net_device *dev) +{ + kfree(dev); +} + /* * Function irda_device_setup (dev) * @@ -385,8 +390,7 @@ int irda_device_setup(struct net_device *dev) dev->hard_header_len = 0; dev->addr_len = 0; - dev->features |= NETIF_F_DYNALLOC; - /* dev->destructor = irda_device_destructor; */ + dev->destructor = irda_device_destructor; dev->type = ARPHRD_IRDA; dev->tx_queue_len = 8; /* Window size + 1 s-frame */ diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index 3776b71b5b90..8639f6a5ea07 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c @@ -62,16 +62,6 @@ int irlan_eth_init(struct net_device *dev) dev->get_stats = irlan_eth_get_stats; dev->set_multicast_list = irlan_eth_set_multicast_list; - /* NETIF_F_DYNALLOC feature was set by irlan_eth_init() and would - * cause the unregister_netdev() to do asynch completion _and_ - * kfree self->dev afterwards. Which is really bad because the - * netdevice was not allocated separately but is embedded in - * our control block and therefore gets freed with *self. - * The only reason why this would have been enabled is to hide - * some netdev refcount issues. If unregister_netdev() blocks - * forever, tell us about it... */ - //dev->features |= NETIF_F_DYNALLOC; - ether_setup(dev); /* -- cgit v1.2.3 From d21c8bd3a242c065d659af1eb252dbfad3fd2ebf Mon Sep 17 00:00:00 2001 From: Chas Williams Date: Wed, 19 Mar 2003 08:45:22 -0800 Subject: [ATM]: Fix idt77252/sch_atm/pppoatm compilation. --- drivers/atm/idt77252.c | 4 ++-- net/atm/pppoatm.c | 2 +- net/sched/sch_atm.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index e337c9e68ed4..3a59d3d3833c 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -730,7 +730,7 @@ push_on_scq(struct idt77252_dev *card, struct vc_map *vc, struct sk_buff *skb) struct atm_vcc *vcc = vc->tx_vcc; vc->estimator->cells += (skb->len + 47) / 48; - if (atomic_read(&vcc->tx_inuse) > (vcc->sk->sndbuf >> 1)) { + if (atomic_read(&vcc->sk->wmem_alloc) > (vcc->sk->sndbuf >> 1)) { u32 cps = vc->estimator->maxcps; vc->estimator->cps = cps; @@ -2025,7 +2025,7 @@ idt77252_send_oam(struct atm_vcc *vcc, void *cell, int flags) atomic_inc(&vcc->stats->tx_err); return -ENOMEM; } - atomic_add(skb->truesize + ATM_PDU_OVHD, &vcc->tx_inuse); + atomic_add(skb->truesize + ATM_PDU_OVHD, &vcc->sk->wmem_alloc); ATM_SKB(skb)->iovcnt = 0; memcpy(skb_put(skb, 52), cell, 52); diff --git a/net/atm/pppoatm.c b/net/atm/pppoatm.c index b9aa77392a80..ee9b5fc8ca93 100644 --- a/net/atm/pppoatm.c +++ b/net/atm/pppoatm.c @@ -231,7 +231,7 @@ static int pppoatm_send(struct ppp_channel *chan, struct sk_buff *skb) kfree_skb(skb); return 1; } - atomic_add(skb->truesize, &ATM_SKB(skb)->vcc->tx_inuse); + atomic_add(skb->truesize, &ATM_SKB(skb)->vcc->sk->wmem_alloc); ATM_SKB(skb)->iovcnt = 0; ATM_SKB(skb)->atm_options = ATM_SKB(skb)->vcc->atm_options; DPRINTK("(unit %d): atm_skb(%p)->vcc(%p)->dev(%p)\n", diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 82533ec23d0a..7eb8564e63c6 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -508,7 +508,7 @@ static void sch_atm_dequeue(unsigned long data) ATM_SKB(skb)->vcc = flow->vcc; memcpy(skb_push(skb,flow->hdr_len),flow->hdr, flow->hdr_len); - atomic_add(skb->truesize,&flow->vcc->tx_inuse); + atomic_add(skb->truesize,&flow->vcc->sk->wmem_alloc); ATM_SKB(skb)->iovcnt = 0; /* atm.atm_options are already set by atm_tc_enqueue */ (void) flow->vcc->send(flow->vcc,skb); -- cgit v1.2.3 From 91bd95691b0b73fe9855a18ad9e1a63208f9ce48 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 19:14:58 -0800 Subject: [PATCH] i2c i2c-ali15x3.c: remove #ifdefs and fix all printk() to use dev_*(). --- drivers/i2c/busses/i2c-ali15x3.c | 115 +++++++++++++++------------------------ 1 file changed, 45 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 8d7f372e109f..fda0d0d64893 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -60,6 +60,8 @@ /* Note: we assume there can only be one ALI15X3, with one SMBus interface */ +/* #define DEBUG 1 */ + #include #include #include @@ -131,7 +133,6 @@ MODULE_PARM_DESC(force_addr, static void ali15x3_do_pause(unsigned int amount); -static int ali15x3_transaction(void); static unsigned short ali15x3_smba = 0; @@ -161,8 +162,8 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev) pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba); ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1)); if (ali15x3_smba == 0 && force_addr == 0) { - printk - ("i2c-ali15x3.o: ALI15X3_smb region uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); + dev_err(&ALI15X3_dev->dev, "ALI15X3_smb region uninitialized " + "- upgrade BIOS or use force_addr=0xaddr\n"); return -ENODEV; } @@ -170,14 +171,15 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev) ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) { - printk - ("i2c-ali15x3.o: ALI15X3_smb region 0x%x already in use!\n", - ali15x3_smba); + dev_err(&ALI15X3_dev->dev, + "ALI15X3_smb region 0x%x already in use!\n", + ali15x3_smba); return -ENODEV; } if(force_addr) { - printk("i2c-ali15x3.o: forcing ISA address 0x%04X\n", ali15x3_smba); + dev_info(&ALI15X3_dev->dev, "forcing ISA address 0x%04X\n", + ali15x3_smba); if (PCIBIOS_SUCCESSFUL != pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba)) return -ENODEV; @@ -186,21 +188,22 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev) return -ENODEV; if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) { /* make sure it works */ - printk("i2c-ali15x3.o: force address failed - not supported?\n"); + dev_err(&ALI15X3_dev->dev, + "force address failed - not supported?\n"); return -ENODEV; } } /* check if whole device is enabled */ pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp); if ((temp & 1) == 0) { - printk("i2c-ali15x3: enabling SMBus device\n"); + dev_info(&ALI15X3_dev->dev, "enabling SMBus device\n"); pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01); } /* Is SMB Host controller enabled? */ pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp); if ((temp & 1) == 0) { - printk("i2c-ali15x3: enabling SMBus controller\n"); + dev_info(&ALI15X3_dev->dev, "enabling SMBus controller\n"); pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01); } @@ -210,18 +213,16 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev) /* Everything is happy, let's grab the memory and set things up. */ request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb"); -#ifdef DEBUG /* The interrupt routing for SMB is set up in register 0x77 in the 1533 ISA Bridge device, NOT in the 7101 device. Don't bother with finding the 1533 device and reading the register. - if ((....... & 0x0F) == 1) - printk("i2c-ali15x3.o: ALI15X3 using Interrupt 9 for SMBus.\n"); + if ((....... & 0x0F) == 1) + dev_dbg(&ALI15X3_dev->dev, "ALI15X3 using Interrupt 9 for SMBus.\n"); */ pci_read_config_byte(ALI15X3_dev, SMBREV, &temp); - printk("i2c-ali15x3.o: SMBREV = 0x%X\n", temp); - printk("i2c-ali15x3.o: ALI15X3_smba = 0x%X\n", ali15x3_smba); -#endif /* DEBUG */ + dev_dbg(&ALI15X3_dev->dev, "SMBREV = 0x%X\n", temp); + dev_dbg(&ALI15X3_dev->dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba); return 0; } @@ -235,19 +236,16 @@ void ali15x3_do_pause(unsigned int amount) } /* Another internally used function */ -int ali15x3_transaction(void) +static int ali15x3_transaction(struct i2c_adapter *adap) { int temp; int result = 0; int timeout = 0; -#ifdef DEBUG - printk - ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, " - "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); -#endif + dev_dbg(&adap->dev, "Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), + inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), + inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); /* get status */ temp = inb_p(SMBHSTSTS); @@ -257,7 +255,7 @@ int ali15x3_transaction(void) if (temp & ALI15X3_STS_BUSY) { /* If the host controller is still busy, it may have timed out in the previous transaction, - resulting in a "SMBus Timeout" printk. + resulting in a "SMBus Timeout" Dev. I've tried the following to reset a stuck busy bit. 1. Reset the controller with an ABORT command. (this doesn't seem to clear the controller if an external device is hung) @@ -268,24 +266,14 @@ int ali15x3_transaction(void) Worst case, nothing seems to work except power reset. */ /* Abort - reset the host controller */ -/* -#ifdef DEBUG - printk("i2c-ali15x3.o: Resetting host controller to clear busy condition\n",temp); -#endif - outb_p(ALI15X3_ABORT, SMBHSTCNT); - temp = inb_p(SMBHSTSTS); - if (temp & ALI15X3_STS_BUSY) { -*/ - /* Try resetting entire SMB bus, including other devices - This may not work either - it clears the BUSY bit but then the BUSY bit may come back on when you try and use the chip again. If that's the case you are stuck. */ - printk - ("i2c-ali15x3.o: Resetting entire SMB Bus to clear busy condition (%02x)\n", - temp); + dev_info(&adap->dev, "Resetting entire SMB Bus to " + "clear busy condition (%02x)\n", temp); outb_p(ALI15X3_T_OUT, SMBHSTCNT); temp = inb_p(SMBHSTSTS); } @@ -302,9 +290,9 @@ int ali15x3_transaction(void) /* this is probably going to be correctable only by a power reset as one of the bits now appears to be stuck */ /* This may be a bus or device with electrical problems. */ - printk - ("i2c-ali15x3.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n", - temp); + dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - " + "controller or device on bus is probably hung\n", + temp); return -1; } } else { @@ -328,14 +316,12 @@ int ali15x3_transaction(void) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { result = -1; - printk("i2c-ali15x3.o: SMBus Timeout!\n"); + dev_err(&adap->dev, "SMBus Timeout!\n"); } if (temp & ALI15X3_STS_TERM) { result = -1; -#ifdef DEBUG - printk("i2c-ali15x3.o: Error: Failed bus transaction\n"); -#endif + dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); } /* @@ -346,25 +332,20 @@ int ali15x3_transaction(void) */ if (temp & ALI15X3_STS_COLL) { result = -1; -#ifdef DEBUG - printk - ("i2c-ali15x3.o: Error: no response or bus collision ADD=%02x\n", - inb_p(SMBHSTADD)); -#endif + dev_dbg(&adap->dev, + "Error: no response or bus collision ADD=%02x\n", + inb_p(SMBHSTADD)); } /* haven't ever seen this */ if (temp & ALI15X3_STS_DEV) { result = -1; - printk("i2c-ali15x3.o: Error: device error\n"); + dev_err(&adap->dev, "Error: device error\n"); } -#ifdef DEBUG - printk - ("i2c-ali15x3.o: Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, " - "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); -#endif + dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, " + "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), + inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), + inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); return result; } @@ -388,14 +369,12 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, temp = inb_p(SMBHSTSTS); } if (timeout >= MAX_TIMEOUT) { - printk("i2c-ali15x3.o: Idle wait Timeout! STS=0x%02x\n", - temp); + dev_err(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp); } switch (size) { case I2C_SMBUS_PROC_CALL: - printk - ("i2c-ali15x3.o: I2C_SMBUS_PROC_CALL not supported!\n"); + dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n"); return -1; case I2C_SMBUS_QUICK: outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), @@ -452,7 +431,7 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, outb_p(size, SMBHSTCNT); /* output command */ - if (ali15x3_transaction()) /* Error in transaction */ + if (ali15x3_transaction(adap)) /* Error in transaction */ return -1; if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) @@ -477,11 +456,8 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */ for (i = 1; i <= data->block[0]; i++) { data->block[i] = inb_p(SMBBLKDAT); -#ifdef DEBUG - printk - ("i2c-ali15x3.o: Blk: len=%d, i=%d, data=%02x\n", - len, i, data->block[i]); -#endif /* DEBUG */ + dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n", + len, i, data->block[i]); } break; } @@ -525,9 +501,8 @@ static struct pci_device_id ali15x3_ids[] __devinitdata = { static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) { if (ali15x3_setup(dev)) { - printk - ("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n"); - + dev_err(&dev->dev, + "ALI15X3 not detected, module not inserted.\n"); return -ENODEV; } -- cgit v1.2.3 From b6afc3923f79337bec99c0110cbc32375aa8df25 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 19:15:18 -0800 Subject: [PATCH] i2c i2c-ali15x3.c: remove check_region() call. --- drivers/i2c/busses/i2c-ali15x3.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index fda0d0d64893..534f51016384 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -170,7 +170,7 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev) if(force_addr) ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); - if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) { + if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb")) { dev_err(&ALI15X3_dev->dev, "ALI15X3_smb region 0x%x already in use!\n", ali15x3_smba); @@ -210,9 +210,6 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev) /* set SMB clock to 74KHz as recommended in data sheet */ pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20); - /* Everything is happy, let's grab the memory and set things up. */ - request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb"); - /* The interrupt routing for SMB is set up in register 0x77 in the 1533 ISA Bridge device, NOT in the 7101 device. -- cgit v1.2.3 From 09a3943b4d23b93aba90ce519faafd6aa4863022 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 19:15:37 -0800 Subject: [PATCH] i2c i2c-ali15x3.c: fix up formatting and whitespace issues. --- drivers/i2c/busses/i2c-ali15x3.c | 184 +++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 96 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c index 534f51016384..cd4569ed952f 100644 --- a/drivers/i2c/busses/i2c-ali15x3.c +++ b/drivers/i2c/busses/i2c-ali15x3.c @@ -73,46 +73,46 @@ #include /* ALI15X3 SMBus address offsets */ -#define SMBHSTSTS (0 + ali15x3_smba) -#define SMBHSTCNT (1 + ali15x3_smba) -#define SMBHSTSTART (2 + ali15x3_smba) -#define SMBHSTCMD (7 + ali15x3_smba) -#define SMBHSTADD (3 + ali15x3_smba) -#define SMBHSTDAT0 (4 + ali15x3_smba) -#define SMBHSTDAT1 (5 + ali15x3_smba) -#define SMBBLKDAT (6 + ali15x3_smba) +#define SMBHSTSTS (0 + ali15x3_smba) +#define SMBHSTCNT (1 + ali15x3_smba) +#define SMBHSTSTART (2 + ali15x3_smba) +#define SMBHSTCMD (7 + ali15x3_smba) +#define SMBHSTADD (3 + ali15x3_smba) +#define SMBHSTDAT0 (4 + ali15x3_smba) +#define SMBHSTDAT1 (5 + ali15x3_smba) +#define SMBBLKDAT (6 + ali15x3_smba) /* PCI Address Constants */ -#define SMBCOM 0x004 -#define SMBBA 0x014 -#define SMBATPC 0x05B /* used to unlock xxxBA registers */ -#define SMBHSTCFG 0x0E0 -#define SMBSLVC 0x0E1 -#define SMBCLK 0x0E2 -#define SMBREV 0x008 +#define SMBCOM 0x004 +#define SMBBA 0x014 +#define SMBATPC 0x05B /* used to unlock xxxBA registers */ +#define SMBHSTCFG 0x0E0 +#define SMBSLVC 0x0E1 +#define SMBCLK 0x0E2 +#define SMBREV 0x008 /* Other settings */ -#define MAX_TIMEOUT 200 /* times 1/100 sec */ -#define ALI15X3_SMB_IOSIZE 32 +#define MAX_TIMEOUT 200 /* times 1/100 sec */ +#define ALI15X3_SMB_IOSIZE 32 /* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB. We don't use these here. If the bases aren't set to some value we tell user to upgrade BIOS and we fail. */ -#define ALI15X3_SMB_DEFAULTBASE 0xE800 +#define ALI15X3_SMB_DEFAULTBASE 0xE800 /* ALI15X3 address lock bits */ -#define ALI15X3_LOCK 0x06 +#define ALI15X3_LOCK 0x06 /* ALI15X3 command constants */ -#define ALI15X3_ABORT 0x02 -#define ALI15X3_T_OUT 0x04 -#define ALI15X3_QUICK 0x00 -#define ALI15X3_BYTE 0x10 -#define ALI15X3_BYTE_DATA 0x20 -#define ALI15X3_WORD_DATA 0x30 -#define ALI15X3_BLOCK_DATA 0x40 -#define ALI15X3_BLOCK_CLR 0x80 +#define ALI15X3_ABORT 0x02 +#define ALI15X3_T_OUT 0x04 +#define ALI15X3_QUICK 0x00 +#define ALI15X3_BYTE 0x10 +#define ALI15X3_BYTE_DATA 0x20 +#define ALI15X3_WORD_DATA 0x30 +#define ALI15X3_BLOCK_DATA 0x40 +#define ALI15X3_BLOCK_CLR 0x80 /* ALI15X3 status register bits */ #define ALI15X3_STS_IDLE 0x04 @@ -131,34 +131,31 @@ MODULE_PARM(force_addr, "i"); MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller"); - -static void ali15x3_do_pause(unsigned int amount); - static unsigned short ali15x3_smba = 0; -int ali15x3_setup(struct pci_dev *ALI15X3_dev) +static int ali15x3_setup(struct pci_dev *ALI15X3_dev) { u16 a; unsigned char temp; -/* Check the following things: - - SMB I/O address is initialized - - Device is enabled - - We can use the addresses -*/ - -/* Unlock the register. - The data sheet says that the address registers are read-only - if the lock bits are 1, but in fact the address registers - are zero unless you clear the lock bits. -*/ + /* Check the following things: + - SMB I/O address is initialized + - Device is enabled + - We can use the addresses + */ + + /* Unlock the register. + The data sheet says that the address registers are read-only + if the lock bits are 1, but in fact the address registers + are zero unless you clear the lock bits. + */ pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp); if (temp & ALI15X3_LOCK) { temp &= ~ALI15X3_LOCK; pci_write_config_byte(ALI15X3_dev, SMBATPC, temp); } -/* Determine the address of the SMBus area */ + /* Determine the address of the SMBus area */ pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba); ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1)); if (ali15x3_smba == 0 && force_addr == 0) { @@ -193,30 +190,30 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev) return -ENODEV; } } -/* check if whole device is enabled */ + /* check if whole device is enabled */ pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp); if ((temp & 1) == 0) { dev_info(&ALI15X3_dev->dev, "enabling SMBus device\n"); pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01); } -/* Is SMB Host controller enabled? */ + /* Is SMB Host controller enabled? */ pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp); if ((temp & 1) == 0) { dev_info(&ALI15X3_dev->dev, "enabling SMBus controller\n"); pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01); } -/* set SMB clock to 74KHz as recommended in data sheet */ + /* set SMB clock to 74KHz as recommended in data sheet */ pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20); -/* - The interrupt routing for SMB is set up in register 0x77 in the - 1533 ISA Bridge device, NOT in the 7101 device. - Don't bother with finding the 1533 device and reading the register. + /* + The interrupt routing for SMB is set up in register 0x77 in the + 1533 ISA Bridge device, NOT in the 7101 device. + Don't bother with finding the 1533 device and reading the register. if ((....... & 0x0F) == 1) dev_dbg(&ALI15X3_dev->dev, "ALI15X3 using Interrupt 9 for SMBus.\n"); -*/ + */ pci_read_config_byte(ALI15X3_dev, SMBREV, &temp); dev_dbg(&ALI15X3_dev->dev, "SMBREV = 0x%X\n", temp); dev_dbg(&ALI15X3_dev->dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba); @@ -224,9 +221,8 @@ int ali15x3_setup(struct pci_dev *ALI15X3_dev) return 0; } - /* Internally used pause function */ -void ali15x3_do_pause(unsigned int amount) +static void ali15x3_do_pause(unsigned int amount) { current->state = TASK_INTERRUPTIBLE; schedule_timeout(amount); @@ -250,33 +246,32 @@ static int ali15x3_transaction(struct i2c_adapter *adap) /* Make sure the SMBus host is ready to start transmitting */ /* Check the busy bit first */ if (temp & ALI15X3_STS_BUSY) { -/* - If the host controller is still busy, it may have timed out in the previous transaction, - resulting in a "SMBus Timeout" Dev. - I've tried the following to reset a stuck busy bit. - 1. Reset the controller with an ABORT command. - (this doesn't seem to clear the controller if an external device is hung) - 2. Reset the controller and the other SMBus devices with a T_OUT command. - (this clears the host busy bit if an external device is hung, - but it comes back upon a new access to a device) - 3. Disable and reenable the controller in SMBHSTCFG - Worst case, nothing seems to work except power reset. -*/ -/* Abort - reset the host controller */ -/* - Try resetting entire SMB bus, including other devices - - This may not work either - it clears the BUSY bit but - then the BUSY bit may come back on when you try and use the chip again. - If that's the case you are stuck. -*/ + /* + If the host controller is still busy, it may have timed out in the + previous transaction, resulting in a "SMBus Timeout" Dev. + I've tried the following to reset a stuck busy bit. + 1. Reset the controller with an ABORT command. + (this doesn't seem to clear the controller if an external + device is hung) + 2. Reset the controller and the other SMBus devices with a + T_OUT command. (this clears the host busy bit if an + external device is hung, but it comes back upon a new access + to a device) + 3. Disable and reenable the controller in SMBHSTCFG + Worst case, nothing seems to work except power reset. + */ + /* Abort - reset the host controller */ + /* + Try resetting entire SMB bus, including other devices - + This may not work either - it clears the BUSY bit but + then the BUSY bit may come back on when you try and use the chip again. + If that's the case you are stuck. + */ dev_info(&adap->dev, "Resetting entire SMB Bus to " "clear busy condition (%02x)\n", temp); outb_p(ALI15X3_T_OUT, SMBHSTCNT); temp = inb_p(SMBHSTSTS); } -/* - } -*/ /* now check the error bits and the busy bit */ if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { @@ -321,12 +316,12 @@ static int ali15x3_transaction(struct i2c_adapter *adap) dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); } -/* - Unfortunately the ALI SMB controller maps "no response" and "bus collision" - into a single bit. No reponse is the usual case so don't - do a printk. - This means that bus collisions go unreported. -*/ + /* + Unfortunately the ALI SMB controller maps "no response" and "bus + collision" into a single bit. No reponse is the usual case so don't + do a printk. + This means that bus collisions go unreported. + */ if (temp & ALI15X3_STS_COLL) { result = -1; dev_dbg(&adap->dev, @@ -334,7 +329,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) inb_p(SMBHSTADD)); } -/* haven't ever seen this */ + /* haven't ever seen this */ if (temp & ALI15X3_STS_DEV) { result = -1; dev_err(&adap->dev, "Error: device error\n"); @@ -347,7 +342,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap) } /* Return -1 on error. */ -s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, +static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data * data) { @@ -355,9 +350,9 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, int temp; int timeout; -/* clear all the bits (clear-on-write) */ + /* clear all the bits (clear-on-write) */ outb_p(0xFF, SMBHSTSTS); -/* make sure SMBus is idle */ + /* make sure SMBus is idle */ temp = inb_p(SMBHSTSTS); for (timeout = 0; (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); @@ -418,7 +413,8 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, data->block[0] = len; } outb_p(len, SMBHSTDAT0); - outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */ + /* Reset SMBBLKDAT */ + outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); for (i = 1; i <= len; i++) outb_p(data->block[i], SMBBLKDAT); } @@ -450,7 +446,8 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, if (len > 32) len = 32; data->block[0] = len; - outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); /* Reset SMBBLKDAT */ + /* Reset SMBBLKDAT */ + outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); for (i = 1; i <= data->block[0]; i++) { data->block[i] = inb_p(SMBBLKDAT); dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n", @@ -461,8 +458,7 @@ s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, return 0; } - -u32 ali15x3_func(struct i2c_adapter *adapter) +static u32 ali15x3_func(struct i2c_adapter *adapter) { return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | @@ -483,8 +479,6 @@ static struct i2c_adapter ali15x3_adapter = { .algo = &smbus_algorithm, }; - - static struct pci_device_id ali15x3_ids[] __devinitdata = { { .vendor = PCI_VENDOR_ID_AL, @@ -529,17 +523,15 @@ static int __init i2c_ali15x3_init(void) return pci_module_init(&ali15x3_driver); } - static void __exit i2c_ali15x3_exit(void) { pci_unregister_driver(&ali15x3_driver); release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); } - - -MODULE_AUTHOR - ("Frodo Looijaard , Philip Edelbrock , and Mark D. Studebaker "); +MODULE_AUTHOR ("Frodo Looijaard , " + "Philip Edelbrock , " + "and Mark D. Studebaker "); MODULE_DESCRIPTION("ALI15X3 SMBus driver"); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From a4639e9db8bec5691efd3645e708df06eac4c509 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 19:15:57 -0800 Subject: [PATCH] i2c i2c-amd756.c: remove some #ifdefs and fix all printk() to use dev_*(). Also some minor whitespace cleanups. --- drivers/i2c/busses/i2c-amd756.c | 138 ++++++++++++++++++++-------------------- 1 file changed, 68 insertions(+), 70 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c index d4bc60ebac3d..86ae2dce1423 100644 --- a/drivers/i2c/busses/i2c-amd756.c +++ b/drivers/i2c/busses/i2c-amd756.c @@ -35,6 +35,8 @@ Note: we assume there can only be one device, with one SMBus interface. */ +/* #define DEBUG 1 */ + #include #include #include @@ -46,44 +48,42 @@ #include #include -#define DRV_NAME "i2c-amd756" - /* AMD756 SMBus address offsets */ -#define SMB_ADDR_OFFSET 0xE0 -#define SMB_IOSIZE 16 -#define SMB_GLOBAL_STATUS (0x0 + amd756_ioport) -#define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport) -#define SMB_HOST_ADDRESS (0x4 + amd756_ioport) -#define SMB_HOST_DATA (0x6 + amd756_ioport) -#define SMB_HOST_COMMAND (0x8 + amd756_ioport) -#define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport) -#define SMB_HAS_DATA (0xA + amd756_ioport) -#define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport) -#define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport) -#define SMB_SNOOP_ADDRESS (0xF + amd756_ioport) +#define SMB_ADDR_OFFSET 0xE0 +#define SMB_IOSIZE 16 +#define SMB_GLOBAL_STATUS (0x0 + amd756_ioport) +#define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport) +#define SMB_HOST_ADDRESS (0x4 + amd756_ioport) +#define SMB_HOST_DATA (0x6 + amd756_ioport) +#define SMB_HOST_COMMAND (0x8 + amd756_ioport) +#define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport) +#define SMB_HAS_DATA (0xA + amd756_ioport) +#define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport) +#define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport) +#define SMB_SNOOP_ADDRESS (0xF + amd756_ioport) /* PCI Address Constants */ /* address of I/O space */ -#define SMBBA 0x058 /* mh */ -#define SMBBANFORCE 0x014 +#define SMBBA 0x058 /* mh */ +#define SMBBANFORCE 0x014 /* general configuration */ -#define SMBGCFG 0x041 /* mh */ +#define SMBGCFG 0x041 /* mh */ /* silicon revision code */ -#define SMBREV 0x008 +#define SMBREV 0x008 /* Other settings */ -#define MAX_TIMEOUT 500 +#define MAX_TIMEOUT 500 /* AMD756 constants */ -#define AMD756_QUICK 0x00 -#define AMD756_BYTE 0x01 -#define AMD756_BYTE_DATA 0x02 -#define AMD756_WORD_DATA 0x03 -#define AMD756_PROCESS_CALL 0x04 -#define AMD756_BLOCK_DATA 0x05 +#define AMD756_QUICK 0x00 +#define AMD756_BYTE 0x01 +#define AMD756_BYTE_DATA 0x02 +#define AMD756_WORD_DATA 0x03 +#define AMD756_PROCESS_CALL 0x04 +#define AMD756_BLOCK_DATA 0x05 static unsigned short amd756_ioport = 0; @@ -101,36 +101,36 @@ static void amd756_do_pause(unsigned int amount) schedule_timeout(amount); } -#define GS_ABRT_STS (1 << 0) -#define GS_COL_STS (1 << 1) -#define GS_PRERR_STS (1 << 2) -#define GS_HST_STS (1 << 3) -#define GS_HCYC_STS (1 << 4) -#define GS_TO_STS (1 << 5) -#define GS_SMB_STS (1 << 11) +#define GS_ABRT_STS (1 << 0) +#define GS_COL_STS (1 << 1) +#define GS_PRERR_STS (1 << 2) +#define GS_HST_STS (1 << 3) +#define GS_HCYC_STS (1 << 4) +#define GS_TO_STS (1 << 5) +#define GS_SMB_STS (1 << 11) -#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ - GS_HCYC_STS | GS_TO_STS ) +#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ + GS_HCYC_STS | GS_TO_STS ) -#define GE_CYC_TYPE_MASK (7) -#define GE_HOST_STC (1 << 3) -#define GE_ABORT (1 << 5) +#define GE_CYC_TYPE_MASK (7) +#define GE_HOST_STC (1 << 3) +#define GE_ABORT (1 << 5) -static int amd756_transaction(void) +static int amd756_transaction(struct i2c_adapter *adap) { int temp; int result = 0; int timeout = 0; - pr_debug(DRV_NAME - ": Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", - inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), - inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); + dev_dbg(&adap->dev, ": Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, " + "DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS), + inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS), + inb_p(SMB_HOST_DATA)); /* Make sure the SMBus host is ready to start transmitting */ if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) { - pr_debug(DRV_NAME ": SMBus busy (%04x). Waiting... \n", temp); + dev_dbg(&adap->dev, ": SMBus busy (%04x). Waiting... \n", temp); do { amd756_do_pause(1); temp = inw_p(SMB_GLOBAL_STATUS); @@ -138,7 +138,7 @@ static int amd756_transaction(void) (timeout++ < MAX_TIMEOUT)); /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { - pr_debug(DRV_NAME ": Busy wait timeout (%04x)\n", temp); + dev_dbg(&adap->dev, ": Busy wait timeout (%04x)\n", temp); goto abort; } timeout = 0; @@ -155,46 +155,46 @@ static int amd756_transaction(void) /* If the SMBus is still busy, we give up */ if (timeout >= MAX_TIMEOUT) { - pr_debug(DRV_NAME ": Completion timeout!\n"); + dev_dbg(&adap->dev, ": Completion timeout!\n"); goto abort; } if (temp & GS_PRERR_STS) { result = -1; - pr_debug(DRV_NAME ": SMBus Protocol error (no response)!\n"); + dev_dbg(&adap->dev, ": SMBus Protocol error (no response)!\n"); } if (temp & GS_COL_STS) { result = -1; - printk(KERN_WARNING DRV_NAME " SMBus collision!\n"); + dev_warn(&adap->dev, " SMBus collision!\n"); } if (temp & GS_TO_STS) { result = -1; - pr_debug(DRV_NAME ": SMBus protocol timeout!\n"); + dev_dbg(&adap->dev, ": SMBus protocol timeout!\n"); } if (temp & GS_HCYC_STS) - pr_debug(DRV_NAME " SMBus protocol success!\n"); + dev_dbg(&adap->dev, " SMBus protocol success!\n"); outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); #ifdef DEBUG if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) { - pr_debug(DRV_NAME - ": Failed reset at end of transaction (%04x)\n", temp); + dev_dbg(&adap->dev, + ": Failed reset at end of transaction (%04x)\n", temp); } - - pr_debug(DRV_NAME - ": Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", - inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), - inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); #endif + dev_dbg(&adap->dev, + ": Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", + inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), + inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); + return result; abort: - printk(KERN_WARNING DRV_NAME ": Sending abort.\n"); + dev_warn(&adap->dev, ": Sending abort.\n"); outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); amd756_do_pause(100); outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); @@ -211,7 +211,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, /** TODO: Should I supporte the 10-bit transfers? */ switch (size) { case I2C_SMBUS_PROC_CALL: - pr_debug(DRV_NAME ": I2C_SMBUS_PROC_CALL not supported!\n"); + dev_dbg(&adap->dev, ": I2C_SMBUS_PROC_CALL not supported!\n"); /* TODO: Well... It is supported, I'm just not sure what to do here... */ return -1; case I2C_SMBUS_QUICK: @@ -266,7 +266,7 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr, /* How about enabling interrupts... */ outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); - if (amd756_transaction()) /* Error in transaction */ + if (amd756_transaction(adap)) /* Error in transaction */ return -1; if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) @@ -334,7 +334,7 @@ static int __devinit amd756_probe(struct pci_dev *pdev, u8 temp; if (amd756_ioport) { - printk(KERN_ERR DRV_NAME ": Only one device supported. " + dev_err(&pdev->dev, ": Only one device supported. " "(you have a strange motherboard, btw..)\n"); return -ENODEV; } @@ -351,8 +351,8 @@ static int __devinit amd756_probe(struct pci_dev *pdev, pci_read_config_byte(pdev, SMBGCFG, &temp); if ((temp & 128) == 0) { - printk(KERN_ERR DRV_NAME - ": Error: SMBus controller I/O not enabled!\n"); + dev_err(&pdev->dev, + ": Error: SMBus controller I/O not enabled!\n"); return -ENODEV; } @@ -364,16 +364,14 @@ static int __devinit amd756_probe(struct pci_dev *pdev, } if (!request_region(amd756_ioport, SMB_IOSIZE, "amd756-smbus")) { - printk(KERN_ERR DRV_NAME - ": SMB region 0x%x already in use!\n", amd756_ioport); + dev_err(&pdev->dev, ": SMB region 0x%x already in use!\n", + amd756_ioport); return -ENODEV; } -#ifdef DEBUG pci_read_config_byte(pdev, SMBREV, &temp); - printk(KERN_DEBUG DRV_NAME ": SMBREV = 0x%X\n", temp); - printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport); -#endif + dev_dbg(&pdev->dev, ": SMBREV = 0x%X\n", temp); + dev_dbg(&pdev->dev, ": AMD756_smba = 0x%X\n", amd756_ioport); /* set up the driverfs linkage to our parent device */ amd756_adapter.dev.parent = &pdev->dev; @@ -383,8 +381,8 @@ static int __devinit amd756_probe(struct pci_dev *pdev, error = i2c_add_adapter(&amd756_adapter); if (error) { - printk(KERN_ERR DRV_NAME - ": Adapter registration failed, module not inserted.\n"); + dev_err(&pdev->dev, + ": Adapter registration failed, module not inserted.\n"); goto out_err; } -- cgit v1.2.3 From 02123a0eba90bc746ffc909f943ff6988c94af98 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 19:16:19 -0800 Subject: [PATCH] i2c i2c-amd8111.c: change a few printk() to dev_warn() --- drivers/i2c/busses/i2c-amd8111.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index 07f22e6e8495..ec3929626b7d 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -74,7 +74,7 @@ unsigned int amd_ec_wait_write(struct amd_smbus *smbus) udelay(1); if (!timeout) { - printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for IBF to clear\n"); + dev_warn(&smbus->dev->dev, "Timeout while waiting for IBF to clear\n"); return -1; } @@ -89,7 +89,7 @@ unsigned int amd_ec_wait_read(struct amd_smbus *smbus) udelay(1); if (!timeout) { - printk(KERN_WARNING "i2c-amd8111.c: Timeout while waiting for OBF to set\n"); + dev_warn(&smbus->dev->dev, "Timeout while waiting for OBF to set\n"); return -1; } @@ -256,11 +256,11 @@ s32 amd8111_access(struct i2c_adapter * adap, u16 addr, unsigned short flags, case I2C_SMBUS_BLOCK_DATA_PEC: case I2C_SMBUS_PROC_CALL_PEC: case I2C_SMBUS_BLOCK_PROC_CALL_PEC: - printk(KERN_WARNING "i2c-amd8111.c: Unexpected software PEC transaction %d\n.", size); + dev_warn(&adap->dev, "Unexpected software PEC transaction %d\n.", size); return -1; default: - printk(KERN_WARNING "i2c-amd8111.c: Unsupported transaction %d\n", size); + dev_warn(&adap->dev, "Unsupported transaction %d\n", size); return -1; } -- cgit v1.2.3 From e639e56b9a6d7b443254a3d56b010db87d4e6b1f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 19:28:11 -0800 Subject: i2c i2c-amd8111.c: change the pci driver name to have "2" in it based on previous comments. --- drivers/i2c/busses/i2c-amd8111.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c index ec3929626b7d..e83bbf9ffd0e 100644 --- a/drivers/i2c/busses/i2c-amd8111.c +++ b/drivers/i2c/busses/i2c-amd8111.c @@ -392,7 +392,7 @@ static void __devexit amd8111_remove(struct pci_dev *dev) } static struct pci_driver amd8111_driver = { - .name = "amd8111 smbus", + .name = "amd8111 smbus 2", .id_table = amd8111_ids, .probe = amd8111_probe, .remove = __devexit_p(amd8111_remove), -- cgit v1.2.3 From 89563a9ebec99b0c0cc96e37aae8cbd722476cba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 19:47:43 -0800 Subject: i2c: added i2c-isa bus controller driver. Based on the i2c cvs version of this driver. --- drivers/i2c/busses/Kconfig | 18 +++++++++++++ drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-isa.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 drivers/i2c/busses/i2c-isa.c (limited to 'drivers') diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 67abe170a8de..a2c20584f7f9 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -76,6 +76,24 @@ config I2C_I801 in the lm_sensors package, which you can download at http://www.lm-sensors.nu +config I2C_ISA + tristate " ISA Bus support" + depends on I2C && I2C_PROC && ISA && EXPERIMENTAL + help + If you say yes to this option, support will be included for i2c + interfaces that are on the ISA bus. + + This can also be built as a module which can be inserted and removed + while the kernel is running. If you want to compile it as a module, + say M here and read . + + The module will be called i2c-isa. + + You will also need the latest user-space utilties: you can find them + in the lm_sensors package, which you can download at + http://www.lm-sensors.nu + + config I2C_PIIX4 tristate " Intel PIIX4" depends on I2C && I2C_PROC && PCI && EXPERIMENTAL diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index c8e61d4a6f88..b6b6ace36f1b 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o obj-$(CONFIG_I2C_I801) += i2c-i801.o +obj-$(CONFIG_I2C_ISA) += i2c-isa.o obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o diff --git a/drivers/i2c/busses/i2c-isa.c b/drivers/i2c/busses/i2c-isa.c new file mode 100644 index 000000000000..73612de6e96c --- /dev/null +++ b/drivers/i2c/busses/i2c-isa.c @@ -0,0 +1,62 @@ +/* + i2c-isa.c - Part of lm_sensors, Linux kernel modules for hardware + monitoring + Copyright (c) 1998, 1999 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* This implements an i2c algorithm/adapter for ISA bus. Not that this is + on first sight very useful; almost no functionality is preserved. + Except that it makes writing drivers for chips which can be on both + the SMBus and the ISA bus very much easier. See lm78.c for an example + of this. */ + +#include +#include +#include +#include +#include + +/* This is the actual algorithm we define */ +static struct i2c_algorithm isa_algorithm = { + .name = "ISA bus algorithm", + .id = I2C_ALGO_ISA, +}; + +/* There can only be one... */ +static struct i2c_adapter isa_adapter = { + .owner = THIS_MODULE, + .name = "ISA main adapter", + .id = I2C_ALGO_ISA | I2C_HW_ISA, + .algo = &isa_algorithm, +}; + +static int __init i2c_isa_init(void) +{ + return i2c_add_adapter(&isa_adapter); +} + +static void __exit i2c_isa_exit(void) +{ + i2c_del_adapter(&isa_adapter); +} + +MODULE_AUTHOR("Frodo Looijaard "); +MODULE_DESCRIPTION("ISA bus access through i2c"); +MODULE_LICENSE("GPL"); + +module_init(i2c_isa_init); +module_exit(i2c_isa_exit); -- cgit v1.2.3 From 64007dd6a34b4b936c04c2d0aefa7ba88d291592 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 20:07:55 -0800 Subject: i2c: add initial driver model support for i2c drivers. --- drivers/i2c/i2c-core.c | 22 ++++++++++++++++++++++ include/linux/i2c.h | 3 +++ 2 files changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 28cc3ec02277..52355c190120 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -53,6 +53,16 @@ static void i2cproc_remove(int bus); #endif /* CONFIG_PROC_FS */ +int i2c_device_probe(struct device *dev) +{ + return -ENODEV; +} + +int i2c_device_remove(struct device *dev) +{ + return 0; +} + /* --------------------------------------------------- * registering functions * --------------------------------------------------- @@ -204,6 +214,16 @@ int i2c_add_driver(struct i2c_driver *driver) drivers[i] = driver; DEB(printk(KERN_DEBUG "i2c-core.o: driver %s registered.\n",driver->name)); + + /* add the driver to the list of i2c drivers in the driver core */ + driver->driver.name = driver->name; + driver->driver.bus = &i2c_bus_type; + driver->driver.probe = i2c_device_probe; + driver->driver.remove = i2c_device_remove; + + res = driver_register(&driver->driver); + if (res) + goto out_unlock; /* now look for instances of driver on our adapters */ @@ -236,6 +256,8 @@ int i2c_del_driver(struct i2c_driver *driver) goto out_unlock; } + driver_unregister(&driver->driver); + /* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver * afterwards. diff --git a/include/linux/i2c.h b/include/linux/i2c.h index a8f482b94ba4..0ae665586de1 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -143,7 +143,10 @@ struct i2c_driver { * with the device. */ int (*command)(struct i2c_client *client,unsigned int cmd, void *arg); + + struct device_driver driver; }; +#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) extern struct bus_type i2c_bus_type; -- cgit v1.2.3 From 67c06c3a6297ae250b53d8871485ac0ef09ecfab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 21:43:12 -0800 Subject: [PATCH] USB: whiteheat bugfix (bugzilla.kernel.org #314) --- drivers/usb/serial/whiteheat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 7738a16f5b40..7acdf0580a3f 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -783,7 +783,7 @@ static int whiteheat_ioctl (struct usb_serial_port *port, struct file * file, un if (info->mcr & UART_MCR_RTS) modem_signals |= TIOCM_RTS; - if (copy_to_user((unsigned int *)arg, &modem_signals, sizeof(unsigned int))); + if (copy_to_user((unsigned int *)arg, &modem_signals, sizeof(unsigned int))) return -EFAULT; break; -- cgit v1.2.3 From 9e54175bf43458becd73326f8589d5c26fd038fb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Mar 2003 21:54:20 -0800 Subject: [PATCH] USB: pegasus: fix up GFP_DMA usages. (bugzilla.kernel.org #418) --- drivers/usb/net/pegasus.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/net/pegasus.c b/drivers/usb/net/pegasus.c index 138ca704f779..a72a4ce7456e 100644 --- a/drivers/usb/net/pegasus.c +++ b/drivers/usb/net/pegasus.c @@ -121,7 +121,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size, char *buffer; DECLARE_WAITQUEUE(wait, current); - buffer = kmalloc(size, GFP_DMA); + buffer = kmalloc(size, GFP_KERNEL); if (!buffer) { warn("%s: looks like we're out of memory", __FUNCTION__); return -ENOMEM; @@ -170,7 +170,7 @@ static int set_registers(pegasus_t * pegasus, __u16 indx, __u16 size, char *buffer; DECLARE_WAITQUEUE(wait, current); - buffer = kmalloc(size, GFP_DMA); + buffer = kmalloc(size, GFP_KERNEL); if (!buffer) { warn("%s: looks like we're out of memory", __FUNCTION__); return -ENOMEM; @@ -218,7 +218,7 @@ static int set_register(pegasus_t * pegasus, __u16 indx, __u8 data) char *tmp; DECLARE_WAITQUEUE(wait, current); - tmp = kmalloc(1, GFP_DMA); + tmp = kmalloc(1, GFP_KERNEL); if (!tmp) { warn("%s: looks like we're out of memory", __FUNCTION__); return -ENOMEM; -- cgit v1.2.3 From 4dc716a14a99376ec27151e24079ca53fc02812d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 19 Mar 2003 22:00:11 -0800 Subject: [PATCH] USB: Update for usb-skeleton My update for usb-skeleton seems to have gotten lost in the shuffle, so here it is again -- all wrapped up in one nice little patch. It's been tested by three different people and passed with flying colors. Please apply. --- drivers/usb/usb-skeleton.c | 229 +++++++++++++++++++++++++++++---------------- 1 file changed, 148 insertions(+), 81 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index b89ca760a959..643d71fc64ea 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -1,5 +1,5 @@ /* - * USB Skeleton driver - 0.9 + * USB Skeleton driver - 1.0 * * Copyright (c) 2001-2002 Greg Kroah-Hartman (greg@kroah.com) * @@ -12,14 +12,17 @@ * USB driver quickly. The design of it is based on the usb-serial and * dc2xx drivers. * - * Thanks to Oliver Neukum and David Brownell for their help in debugging - * this driver. + * Thanks to Oliver Neukum, David Brownell, and Alan Stern for their help + * in debugging this driver. * - * TODO: - * - fix urb->status race condition in write sequence * * History: * + * 2003-02-25 - 1.0 - fix races involving urb->status, unlink_urb(), and + * disconnect. Fix transfer amount in read(). Use + * macros instead of magic numbers in probe(). Change + * size variables to size_t. Show how to eliminate + * DMA bounce buffer. * 2002_12_12 - 0.9 - compile fixes and got rid of fixed minor array. * 2002_09_26 - 0.8 - changes due to USB core conversion to struct device * driver. @@ -33,7 +36,7 @@ * 2001_05_29 - 0.3 - more bug fixes based on review from linux-usb-devel * 2001_05_24 - 0.2 - bug fixes based on review from linux-usb-devel people * 2001_05_01 - 0.1 - first version - * + * */ #include @@ -42,8 +45,8 @@ #include #include #include -#include #include +#include #include #include #include @@ -60,7 +63,7 @@ /* Version Information */ -#define DRIVER_VERSION "v0.4" +#define DRIVER_VERSION "v1.0" #define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com" #define DRIVER_DESC "USB Skeleton Driver" @@ -101,15 +104,16 @@ struct usb_skel { char num_bulk_out; /* number of bulk out endpoints we have */ unsigned char * bulk_in_buffer; /* the buffer to receive data */ - int bulk_in_size; /* the size of the receive buffer */ + size_t bulk_in_size; /* the size of the receive buffer */ __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ unsigned char * bulk_out_buffer; /* the buffer to send data */ - int bulk_out_size; /* the size of the send buffer */ + size_t bulk_out_size; /* the size of the send buffer */ struct urb * write_urb; /* the urb used to send data */ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ + atomic_t write_busy; /* true iff write urb is busy */ + struct completion write_finished; /* wait for the write to finish */ - struct work_struct work; /* work queue entry for line discipline waking up */ int open; /* if the port is open or not */ struct semaphore sem; /* locks this structure */ }; @@ -118,6 +122,8 @@ struct usb_skel { /* the global usb devfs handle */ extern devfs_handle_t usb_devfs_handle; +/* prevent races between open() and disconnect() */ +static DECLARE_MUTEX (disconnect_sem); /* local function prototypes */ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t *ppos); @@ -125,7 +131,7 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count, static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); static int skel_open (struct inode *inode, struct file *file); static int skel_release (struct inode *inode, struct file *file); - + static int skel_probe (struct usb_interface *intf, const struct usb_device_id *id); static void skel_disconnect (struct usb_interface *intf); @@ -138,7 +144,7 @@ static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs); * to have a node in the /dev directory. If the USB * device were for a network interface then the driver * would use "struct net_driver" instead, and a serial - * device would use "struct tty_driver". + * device would use "struct tty_driver". */ static struct file_operations skel_fops = { /* @@ -167,7 +173,7 @@ static struct file_operations skel_fops = { .ioctl = skel_ioctl, .open = skel_open, .release = skel_release, -}; +}; /* usb specific object needed to register this driver with the usb subsystem */ @@ -188,8 +194,8 @@ static inline void usb_skel_debug_data (const char *function, int size, const un if (!debug) return; - - printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", + + printk (KERN_DEBUG __FILE__": %s - length = %d, data = ", function, size); for (i = 0; i < size; ++i) { printk ("%.2x ", data[i]); @@ -206,7 +212,9 @@ static inline void skel_delete (struct usb_skel *dev) if (dev->bulk_in_buffer != NULL) kfree (dev->bulk_in_buffer); if (dev->bulk_out_buffer != NULL) - kfree (dev->bulk_out_buffer); + usb_buffer_free (dev->udev, dev->bulk_out_size, + dev->bulk_out_buffer, + dev->write_urb->transfer_dma); if (dev->write_urb != NULL) usb_free_urb (dev->write_urb); kfree (dev); @@ -222,22 +230,28 @@ static int skel_open (struct inode *inode, struct file *file) struct usb_interface *interface; int subminor; int retval = 0; - + dbg("%s", __FUNCTION__); subminor = minor (inode->i_rdev); + /* prevent disconnects */ + down (&disconnect_sem); + interface = usb_find_interface (&skel_driver, mk_kdev(USB_MAJOR, subminor)); if (!interface) { err ("%s - error, can't find device for minor %d", __FUNCTION__, subminor); - return -ENODEV; + retval = -ENODEV; + goto exit_no_device; } - + dev = usb_get_intfdata(interface); - if (!dev) - return -ENODEV; + if (!dev) { + retval = -ENODEV; + goto exit_no_device; + } /* lock this device */ down (&dev->sem); @@ -251,6 +265,8 @@ static int skel_open (struct inode *inode, struct file *file) /* unlock this device */ up (&dev->sem); +exit_no_device: + up (&disconnect_sem); return retval; } @@ -280,6 +296,12 @@ static int skel_release (struct inode *inode, struct file *file) goto exit_not_opened; } + /* wait for any bulk writes that might be going on to finish up */ + if (atomic_read (&dev->write_busy)) + wait_for_completion (&dev->write_finished); + + dev->open = 0; + if (dev->udev == NULL) { /* the device was unplugged before the file was released */ up (&dev->sem); @@ -287,11 +309,6 @@ static int skel_release (struct inode *inode, struct file *file) return 0; } - /* shutdown any bulk writes that might be going on */ - usb_unlink_urb (dev->write_urb); - - dev->open = 0; - exit_not_opened: up (&dev->sem); @@ -308,7 +325,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t int retval = 0; dev = (struct usb_skel *)file->private_data; - + dbg("%s - minor %d, count = %d", __FUNCTION__, dev->minor, count); /* lock this object */ @@ -319,12 +336,13 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t up (&dev->sem); return -ENODEV; } - - /* do an immediate bulk read to get data from the device */ + + /* do a blocking bulk read to get data from the device */ retval = usb_bulk_msg (dev->udev, - usb_rcvbulkpipe (dev->udev, + usb_rcvbulkpipe (dev->udev, dev->bulk_in_endpointAddr), - dev->bulk_in_buffer, dev->bulk_in_size, + dev->bulk_in_buffer, + min (dev->bulk_in_size, count), &count, HZ*10); /* if the read was successful, copy the data to userspace */ @@ -334,7 +352,7 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t else retval = count; } - + /* unlock the device */ up (&dev->sem); return retval; @@ -343,6 +361,18 @@ static ssize_t skel_read (struct file *file, char *buffer, size_t count, loff_t /** * skel_write + * + * A device driver has to decide how to report I/O errors back to the + * user. The safest course is to wait for the transfer to finish before + * returning so that any errors will be reported reliably. skel_read() + * works like this. But waiting for I/O is slow, so many drivers only + * check for errors during I/O initiation and do not report problems + * that occur during the actual transfer. That's what we will do here. + * + * A driver concerned with maximum I/O throughput would use double- + * buffering: Two urbs would be devoted to write transfers, so that + * one urb could always be active while the other was waiting for the + * user to send more data. */ static ssize_t skel_write (struct file *file, const char *buffer, size_t count, loff_t *ppos) { @@ -369,37 +399,38 @@ static ssize_t skel_write (struct file *file, const char *buffer, size_t count, goto exit; } - /* see if we are already in the middle of a write */ - if (dev->write_urb->status == -EINPROGRESS) { - dbg ("%s - already writing", __FUNCTION__); - goto exit; - } + /* wait for a previous write to finish up; we don't use a timeout + * and so a nonresponsive device can delay us indefinitely. + */ + if (atomic_read (&dev->write_busy)) + wait_for_completion (&dev->write_finished); - /* we can only write as much as 1 urb will hold */ - bytes_written = (count > dev->bulk_out_size) ? - dev->bulk_out_size : count; + /* we can only write as much as our buffer will hold */ + bytes_written = min (dev->bulk_out_size, count); - /* copy the data from userspace into our urb */ - if (copy_from_user(dev->write_urb->transfer_buffer, buffer, + /* copy the data from userspace into our transfer buffer; + * this is the only copy required. + */ + if (copy_from_user(dev->write_urb->transfer_buffer, buffer, bytes_written)) { retval = -EFAULT; goto exit; } - usb_skel_debug_data (__FUNCTION__, bytes_written, + usb_skel_debug_data (__FUNCTION__, bytes_written, dev->write_urb->transfer_buffer); - /* set up our urb */ - usb_fill_bulk_urb(dev->write_urb, dev->udev, - usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr), - dev->write_urb->transfer_buffer, bytes_written, - skel_write_bulk_callback, dev); + /* this urb was already set up, except for this write size */ + dev->write_urb->transfer_buffer_length = bytes_written; /* send the data out the bulk port */ /* a character device write uses GFP_KERNEL, unless a spinlock is held */ + init_completion (&dev->write_finished); + atomic_set (&dev->write_busy, 1); retval = usb_submit_urb(dev->write_urb, GFP_KERNEL); if (retval) { + atomic_set (&dev->write_busy, 0); err("%s - failed submitting write urb, error %d", __FUNCTION__, retval); } else { @@ -435,12 +466,11 @@ static int skel_ioctl (struct inode *inode, struct file *file, unsigned int cmd, dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __FUNCTION__, dev->minor, cmd, arg); - /* fill in your device specific stuff here */ - + /* unlock the device */ up (&dev->sem); - + /* return that we did not understand this ioctl call */ return -ENOTTY; } @@ -455,14 +485,16 @@ static void skel_write_bulk_callback (struct urb *urb, struct pt_regs *regs) dbg("%s - minor %d", __FUNCTION__, dev->minor); - if ((urb->status != -ENOENT) && - (urb->status != -ECONNRESET)) { + /* sync/async unlink faults aren't errors */ + if (urb->status && !(urb->status == -ENOENT || + urb->status == -ECONNRESET)) { dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, urb->status); - return; } - return; + /* notify anyone waiting that the write has finished */ + atomic_set (&dev->write_busy, 0); + complete (&dev->write_finished); } @@ -479,12 +511,12 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; int minor; - int buffer_size; + size_t buffer_size; int i; int retval; char name[10]; - + /* See if the device offered us matches what we can accept */ if ((udev->descriptor.idVendor != USB_SKEL_VENDOR_ID) || (udev->descriptor.idProduct != USB_SKEL_PRODUCT_ID)) { @@ -513,12 +545,15 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i /* set up the endpoint information */ /* check out the endpoints */ + /* use only the first bulk-in and bulk-out endpoints */ iface_desc = &interface->altsetting[0]; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; - if ((endpoint->bEndpointAddress & 0x80) && - ((endpoint->bmAttributes & 3) == 0x02)) { + if (!dev->bulk_in_endpointAddr && + (endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk in endpoint */ buffer_size = endpoint->wMaxPacketSize; dev->bulk_in_size = buffer_size; @@ -529,9 +564,11 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i goto error; } } - - if (((endpoint->bEndpointAddress & 0x80) == 0x00) && - ((endpoint->bmAttributes & 3) == 0x02)) { + + if (!dev->bulk_out_endpointAddr && + !(endpoint->bEndpointAddress & USB_DIR_IN) && + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) + == USB_ENDPOINT_XFER_BULK)) { /* we found a bulk out endpoint */ /* a probe() may sleep and has no restrictions on memory allocations */ dev->write_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -539,40 +576,56 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i err("No free urbs available"); goto error; } + dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; + + /* on some platforms using this kind of buffer alloc + * call eliminates a dma "bounce buffer". + * + * NOTE: you'd normally want i/o buffers that hold + * more than one packet, so that i/o delays between + * packets don't hurt throughput. + */ buffer_size = endpoint->wMaxPacketSize; dev->bulk_out_size = buffer_size; - dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; - dev->bulk_out_buffer = kmalloc (buffer_size, GFP_KERNEL); + dev->write_urb->transfer_flags = (URB_NO_DMA_MAP | + URB_ASYNC_UNLINK); + dev->bulk_out_buffer = usb_buffer_alloc (udev, + buffer_size, GFP_KERNEL, + &dev->write_urb->transfer_dma); if (!dev->bulk_out_buffer) { err("Couldn't allocate bulk_out_buffer"); goto error; } - usb_fill_bulk_urb(dev->write_urb, udev, - usb_sndbulkpipe(udev, + usb_fill_bulk_urb(dev->write_urb, udev, + usb_sndbulkpipe(udev, endpoint->bEndpointAddress), dev->bulk_out_buffer, buffer_size, skel_write_bulk_callback, dev); } } + if (!(dev->bulk_in_endpointAddr && dev->bulk_out_endpointAddr)) { + err("Couldn't find both bulk-in and bulk-out endpoints"); + goto error; + } /* initialize the devfs node for this device and register it */ sprintf(name, "skel%d", dev->minor); - + dev->devfs = devfs_register (usb_devfs_handle, name, DEVFS_FL_DEFAULT, USB_MAJOR, dev->minor, - S_IFCHR | S_IRUSR | S_IWUSR | - S_IRGRP | S_IWGRP | S_IROTH, + S_IFCHR | S_IRUSR | S_IWUSR | + S_IRGRP | S_IWGRP | S_IROTH, &skel_fops, NULL); /* let the user know what node this device is now attached to */ - info ("USB Skeleton device now attached to USBSkel%d", dev->minor); + info ("USB Skeleton device now attached to USBSkel-%d", dev->minor); /* add device id so the device works when advertised */ interface->kdev = mk_kdev(USB_MAJOR, dev->minor); goto exit; - + error: skel_delete (dev); dev = NULL; @@ -593,12 +646,21 @@ exit: * skel_disconnect * * Called by the usb core when the device is removed from the system. + * + * This routine guarantees that the driver will not submit any more urbs + * by clearing dev->udev. It is also supposed to terminate any currently + * active urbs. Unfortunately, usb_bulk_msg(), used in skel_read(), does + * not provide any way to do this. But at least we can cancel an active + * write. */ static void skel_disconnect(struct usb_interface *interface) { struct usb_skel *dev; int minor; + /* prevent races with open() */ + down (&disconnect_sem); + dev = usb_get_intfdata (interface); usb_set_intfdata (interface, NULL); @@ -606,7 +668,7 @@ static void skel_disconnect(struct usb_interface *interface) return; down (&dev->sem); - + /* remove device id to disable open() */ interface->kdev = NODEV; @@ -617,15 +679,21 @@ static void skel_disconnect(struct usb_interface *interface) /* give back our dynamic minor */ usb_deregister_dev (1, minor); - + + /* terminate an ongoing write */ + if (atomic_read (&dev->write_busy)) { + usb_unlink_urb (dev->write_urb); + wait_for_completion (&dev->write_finished); + } + + dev->udev = NULL; + up (&dev->sem); + /* if the device is not opened, then we clean up right now */ - if (!dev->open) { - up (&dev->sem); + if (!dev->open) skel_delete (dev); - } else { - dev->udev = NULL; - up (&dev->sem); - } + + up (&disconnect_sem); info("USB Skeleton #%d now disconnected", minor); } @@ -668,4 +736,3 @@ module_exit (usb_skel_exit); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -- cgit v1.2.3 From 2dbb836f224ddafe391b179a96730ded1a1c0c1e Mon Sep 17 00:00:00 2001 From: Jason McMullan Date: Wed, 19 Mar 2003 22:03:23 -0800 Subject: [PATCH] USB HID: Ignore P5 Data Glove (2.4 and 2.5 patches) As requested, here are the 2.4 (latest BK tree) and 2.5 (latest bk tree) patches to ignore the non-HID Essential Reality Data Glove (again, user-space lib to access this device via /proc/bus/usb is available at http://www.evillabs.net/~jmcc/p5) --- drivers/usb/input/hid-core.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/input/hid-core.c b/drivers/usb/input/hid-core.c index 4da30222593a..9ec19ad566ef 100644 --- a/drivers/usb/input/hid-core.c +++ b/drivers/usb/input/hid-core.c @@ -1334,6 +1334,9 @@ void hid_init_reports(struct hid_device *hid) #define USB_VENDOR_ID_TANGTOP 0x0d3d #define USB_DEVICE_ID_TANGTOP_USBPS2 0x0001 +#define USB_VENDOR_ID_ESSENTIAL_REALITY 0x0d7f +#define USB_DEVICE_ID_ESSENTIAL_REALITY_P5 0x0100 + struct hid_blacklist { __u16 idVendor; __u16 idProduct; @@ -1377,6 +1380,7 @@ struct hid_blacklist { { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_TANGTOP, USB_DEVICE_ID_TANGTOP_USBPS2, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE }, { 0, 0 } }; -- cgit v1.2.3 From e5fb15f9d6162f76fbd7dcad3b44f7d71ddab38a Mon Sep 17 00:00:00 2001 From: Henning Meier-Geinitz Date: Wed, 19 Mar 2003 22:03:46 -0800 Subject: [PATCH] USB: new ids for scanner driver This patch adds new vendor/product ids for various scanners. --- drivers/usb/image/scanner.c | 5 +++-- drivers/usb/image/scanner.h | 13 +++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/image/scanner.c b/drivers/usb/image/scanner.c index 6fb7c46362d6..284baf47656f 100644 --- a/drivers/usb/image/scanner.c +++ b/drivers/usb/image/scanner.c @@ -347,8 +347,9 @@ * - Don't print errors when the device is busy. * * 0.4.11 2003-02-25 - * - Added vendor/product ids for Artec, Avision, Brother, Medion, Primax, - * Prolink, Fujitsu, Plustek, and SYSCAN scanners. + * - Added vendor/product ids for Artec, Avision, Brother, Canon, Compaq, + * Fujitsu, Hewlett-Packard, Lexmark, LG Electronics, Medion, Microtek, + * Primax, Prolink, Plustek, SYSCAN, Trust and UMAX scanners. * - Fixed generation of devfs names if dynamic minors are disabled. * - Used kobject reference counting to free the scn struct when the device * is closed and disconnected. Avoids crashes when writing to a diff --git a/drivers/usb/image/scanner.h b/drivers/usb/image/scanner.h index dc77eb090dec..230f08c307b7 100644 --- a/drivers/usb/image/scanner.h +++ b/drivers/usb/image/scanner.h @@ -105,6 +105,7 @@ static struct usb_device_id scanner_device_ids [] = { { USB_DEVICE(0x0638, 0x0a10) }, /* iVina FB1600 (=Umax Astra 4500) */ /* Benq: see Acer */ /* Brother */ + { USB_DEVICE(0x04f9, 0x010f) }, /* MFC 5100C */ { USB_DEVICE(0x04f9, 0x0111) }, /* MFC 6800 */ /* Canon */ { USB_DEVICE(0x04a9, 0x2201) }, /* CanoScan FB320U */ @@ -118,9 +119,11 @@ static struct usb_device_id scanner_device_ids [] = { { USB_DEVICE(0x04a9, 0x220c) }, /* CanoScan D1250U2 */ { USB_DEVICE(0x04a9, 0x220d) }, /* CanoScan N670U/N676U/LIDE 20 */ { USB_DEVICE(0x04a9, 0x220e) }, /* CanoScan N1240U/LIDE 30 */ + { USB_DEVICE(0x04a9, 0x2213) }, /* LIDE 50 */ { USB_DEVICE(0x04a9, 0x3042) }, /* FS4000US */ /* Colorado -- See Primax/Colorado below */ /* Compaq */ + { USB_DEVICE(0x049f, 0x001a) }, /* S4 100 */ { USB_DEVICE(0x049f, 0x0021) }, /* S200 */ /* Epson -- See Seiko/Epson below */ /* Fujitsu */ @@ -152,6 +155,8 @@ static struct usb_device_id scanner_device_ids [] = { { USB_DEVICE(0x03f0, 0x0705) }, /* ScanJet 4400C */ // { USB_DEVICE(0x03f0, 0x0801) }, /* ScanJet 7400C - NOT SUPPORTED - use hpusbscsi driver */ { USB_DEVICE(0x03f0, 0x0901) }, /* ScanJet 2300C */ + { USB_DEVICE(0x03F0, 0x1005) }, /* ScanJet 5400C */ + { USB_DEVICE(0x03F0, 0x1105) }, /* ScanJet 5470C */ { USB_DEVICE(0x03f0, 0x1305) }, /* Scanjet 4570c */ { USB_DEVICE(0x03f0, 0x2005) }, /* ScanJet 3570c */ { USB_DEVICE(0x03f0, 0x2205) }, /* ScanJet 3500c */ @@ -159,12 +164,16 @@ static struct usb_device_id scanner_device_ids [] = { { USB_DEVICE(0x0638, 0x0268) }, /* 1200U */ /* Lexmark */ { USB_DEVICE(0x043d, 0x002d) }, /* X70/X73 */ + { USB_DEVICE(0x043d, 0x003d) }, /* X83 */ + /* LG Electronics */ + { USB_DEVICE(0x0461, 0x0364) }, /* Scanworks 600U (repackaged Primax?) */ /* Medion */ { USB_DEVICE(0x0461, 0x0377) }, /* MD 5345 - repackaged Primax? */ /* Memorex */ { USB_DEVICE(0x0461, 0x0346) }, /* 6136u - repackaged Primax ? */ /* Microtek */ { USB_DEVICE(0x05da, 0x30ce) }, /* ScanMaker 3800 */ + { USB_DEVICE(0x05da, 0x30cf) }, /* ScanMaker 4800 */ /* The following SCSI-over-USB Microtek devices are supported by the microtek driver: Enable SCSI and USB Microtek in kernel config */ // { USB_DEVICE(0x05da, 0x0099) }, /* ScanMaker X6 - X6U */ @@ -259,7 +268,11 @@ static struct usb_device_id scanner_device_ids [] = { { USB_DEVICE(0x04b8, 0x0802) }, /* Stylus CX3200 */ /* SYSCAN */ { USB_DEVICE(0x0a82, 0x4600) }, /* TravelScan 460/464 */ + /* Trust */ + { USB_DEVICE(0x05cb, 0x1483) }, /* CombiScan 19200 */ + { USB_DEVICE(0x05d8, 0x4006) }, /* Easy Webscan 19200 (repackaged Artec?) */ /* Umax */ + { USB_DEVICE(0x05d8, 0x4009) }, /* Astraslim (actually Artec?) */ { USB_DEVICE(0x1606, 0x0010) }, /* Astra 1220U */ { USB_DEVICE(0x1606, 0x0030) }, /* Astra 2000U */ { USB_DEVICE(0x1606, 0x0060) }, /* Astra 3400U/3450U */ -- cgit v1.2.3 From 24bbcc04f00f3f2251e47218deaf9fe81a07b6f4 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:05:39 -0500 Subject: [E100] back out memleak patch cuz it messed up following On Thu, 20 Mar 2003, Scott Feldman wrote: * Back this patch out - we'll add it later. I was working against 2.5.64 when this was checked into 2.5.65, so it messed up my patches. --- drivers/net/e100/e100_main.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 1f1f70caca21..523e83f771da 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -3784,15 +3784,11 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) return -EOPNOTSUPP; } - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) { - kfree(strings); + if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) return -EFAULT; - } - if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) { - kfree(strings); + if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) return -EFAULT; - } kfree(strings); return 0; -- cgit v1.2.3 From 5fc57f6e3182061ac7c6700427573dab2ec1e128 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:06:16 -0500 Subject: [E100] update version, copyright year, changelog On Thu, 20 Mar 2003, Scott Feldman wrote: * Update version, copyright year, changelog --- drivers/net/e100/e100.h | 2 +- drivers/net/e100/e100_config.c | 2 +- drivers/net/e100/e100_config.h | 2 +- drivers/net/e100/e100_eeprom.c | 2 +- drivers/net/e100/e100_main.c | 33 +++++++++++++++++++-------------- drivers/net/e100/e100_phy.c | 2 +- drivers/net/e100/e100_phy.h | 2 +- drivers/net/e100/e100_test.c | 2 +- drivers/net/e100/e100_ucode.h | 2 +- 9 files changed, 27 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h index 761628d8b586..199848bcc8f2 100644 --- a/drivers/net/e100/e100.h +++ b/drivers/net/e100/e100.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e100/e100_config.c b/drivers/net/e100/e100_config.c index bff330628916..24ac5b371b3b 100644 --- a/drivers/net/e100/e100_config.c +++ b/drivers/net/e100/e100_config.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e100/e100_config.h b/drivers/net/e100/e100_config.h index 5bc88f6849b6..ef3356e4380f 100644 --- a/drivers/net/e100/e100_config.h +++ b/drivers/net/e100/e100_config.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e100/e100_eeprom.c b/drivers/net/e100/e100_eeprom.c index c5618c1a2ca4..ff843e161b76 100644 --- a/drivers/net/e100/e100_eeprom.c +++ b/drivers/net/e100/e100_eeprom.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 523e83f771da..1194fe6e271d 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -45,8 +45,22 @@ **********************************************************************/ /* Change Log - * - * 2.1.29 12/20/02 + * + * 2.2.21 02/11/03 + * o Removed marketing brand strings. Instead, Using generic string + * "Intel(R) PRO/100 Network Connection" for all adapters. + * o Implemented ethtool -S option + * o Strip /proc/net/PRO_LAN_Adapters files for kernel driver + * o Bug fix: Read wrong byte in EEPROM when offset is odd number + * o Bug fix: PHY loopback test fails on ICH devices + * o Bug fix: System panic on e100_close when repeating Hot Remove and + * Add in a team + * o Bug fix: Linux Bonding driver claims adapter's link loss because of + * not updating last_rx field + * o Bug fix: e100 does not check validity of MAC address + * o New feature: added ICH5 support + * + * 2.1.27 11/20/02 * o Bug fix: Device command timeout due to SMBus processing during init * o Bug fix: Not setting/clearing I (Interrupt) bit in tcb correctly * o Bug fix: Not using EEPROM WoL setting as default in ethtool @@ -62,15 +76,6 @@ * ifconfig down, rmmod and insmod * * 2.1.24 10/7/02 - * o Bug fix: Wrong files under /proc/net/PRO_LAN_Adapters/ when interface - * name is changed - * o Bug fix: Rx skb corruption when Rx polling code and Rx interrupt code - * are executing during stress traffic at shared interrupt system. - * Removed Rx polling code - * o Added detailed printk if selftest failed when insmod - * o Removed misleading printks - * - * 2.1.12 8/2/02 */ #include @@ -136,8 +141,8 @@ static void e100_free_nontx_list(struct e100_private *); static void e100_non_tx_background(unsigned long); /* Global Data structures and variables */ -char e100_copyright[] __devinitdata = "Copyright (c) 2002 Intel Corporation"; -char e100_driver_version[]="2.1.29-k4"; +char e100_copyright[] __devinitdata = "Copyright (c) 2003 Intel Corporation"; +char e100_driver_version[]="2.2.21-k1"; const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver"; char e100_short_driver_name[] = "e100"; static int e100nics = 0; diff --git a/drivers/net/e100/e100_phy.c b/drivers/net/e100/e100_phy.c index c8f9053992e1..4f291584b53e 100644 --- a/drivers/net/e100/e100_phy.c +++ b/drivers/net/e100/e100_phy.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e100/e100_phy.h b/drivers/net/e100/e100_phy.h index 51d5ff192700..9335f70a9b51 100644 --- a/drivers/net/e100/e100_phy.h +++ b/drivers/net/e100/e100_phy.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e100/e100_test.c b/drivers/net/e100/e100_test.c index 27ff5af00bfd..147ce34731bc 100644 --- a/drivers/net/e100/e100_test.c +++ b/drivers/net/e100/e100_test.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e100/e100_ucode.h b/drivers/net/e100/e100_ucode.h index 1c6b88c7fac3..ccbcd05583aa 100644 --- a/drivers/net/e100/e100_ucode.h +++ b/drivers/net/e100/e100_ucode.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -- cgit v1.2.3 From bd974bb34440f6cb083ca5d976ed543fd4930735 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:06:35 -0500 Subject: [E100] Spelling mistakes On Thu, 20 Mar 2003, Scott Feldman wrote: * Spelling mistakes --- drivers/net/e100/e100_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 1194fe6e271d..6a1379504bb9 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -2687,13 +2687,12 @@ e100_sw_reset(struct e100_private *bdp, u32 reset_cmd) udelay(20); } - /* Mask off our interrupt line -- its unmasked after reset */ + /* Mask off our interrupt line -- it is unmasked after reset */ e100_disable_clear_intr(bdp); #ifdef E100_CU_DEBUG bdp->last_cmd = 0; bdp->last_sub_cmd = 0; #endif - } /** -- cgit v1.2.3 From df245a2a13ece3debf092732cffb800d59801f96 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:06:55 -0500 Subject: [E100] Add support for VLAN hw offload On Thu, 20 Mar 2003, Scott Feldman wrote: * Add support for VLAN hw offload --- drivers/net/e100/e100.h | 4 ++- drivers/net/e100/e100_config.c | 19 +++++++++++ drivers/net/e100/e100_config.h | 2 +- drivers/net/e100/e100_main.c | 77 +++++++++++++++++++++++++++++++++++------- 4 files changed, 87 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h index 199848bcc8f2..704c4c738d46 100644 --- a/drivers/net/e100/e100.h +++ b/drivers/net/e100/e100.h @@ -57,6 +57,7 @@ #include #include #include +#include #define E100_REGS_LEN 1 /* @@ -358,7 +359,7 @@ struct driver_stats { #define CB_STATUS_MASK BIT_12_15 /* CB Status Mask (4-bits) */ #define CB_STATUS_COMPLETE BIT_15 /* CB Complete Bit */ #define CB_STATUS_OK BIT_13 /* CB OK Bit */ -#define CB_STATUS_UNDERRUN BIT_12 /* CB A Bit */ +#define CB_STATUS_VLAN BIT_12 /* CB Valn detected Bit */ #define CB_STATUS_FAIL BIT_11 /* CB Fail (F) Bit */ /*misc command bits */ @@ -851,6 +852,7 @@ struct ethtool_lpbk_data{ }; struct e100_private { + struct vlan_group *vlgrp; u32 flags; /* board management flags */ u32 tx_per_underrun; /* number of good tx frames per underrun */ unsigned int tx_count; /* count of tx frames, so we can request an interrupt */ diff --git a/drivers/net/e100/e100_config.c b/drivers/net/e100/e100_config.c index 24ac5b371b3b..d9df35677a7c 100644 --- a/drivers/net/e100/e100_config.c +++ b/drivers/net/e100/e100_config.c @@ -521,6 +521,25 @@ e100_config_wol(struct e100_private *bdp) spin_unlock_bh(&(bdp->config_lock)); } +void +e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable) +{ + spin_lock_bh(&(bdp->config_lock)); + if (enable) { + if (!(bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) { + bdp->config[22] |= CB_CFIG_VLAN_DROP_ENABLE; + E100_CONFIG(bdp, 22); + } + + } else { + if ((bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) { + bdp->config[22] &= ~CB_CFIG_VLAN_DROP_ENABLE; + E100_CONFIG(bdp, 22); + } + } + spin_unlock_bh(&(bdp->config_lock)); +} + /** * e100_config_loopback_mode * @bdp: atapter's private data struct diff --git a/drivers/net/e100/e100_config.h b/drivers/net/e100/e100_config.h index ef3356e4380f..5d1e194ff25b 100644 --- a/drivers/net/e100/e100_config.h +++ b/drivers/net/e100/e100_config.h @@ -163,5 +163,5 @@ extern void e100_config_force_dplx(struct e100_private *bdp); extern u8 e100_config_loopback_mode(struct e100_private *bdp, u8 mode); extern u8 e100_config_dynamic_tbd(struct e100_private *bdp, u8 enable); extern u8 e100_config_tcb_ext_enable(struct e100_private *bdp, u8 enable); - +extern void e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable); #endif /* _E100_CONFIG_INC_ */ diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 6a1379504bb9..47e818a8358a 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -146,6 +146,10 @@ char e100_driver_version[]="2.2.21-k1"; const char *e100_full_driver_name = "Intel(R) PRO/100 Network Driver"; char e100_short_driver_name[] = "e100"; static int e100nics = 0; +static void e100_vlan_rx_register(struct net_device *netdev, struct vlan_group + *grp); +static void e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid); +static void e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid); #ifdef CONFIG_PM static int e100_notify_reboot(struct notifier_block *, unsigned long event, void *ptr); @@ -651,6 +655,9 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) goto err_pci; } + dev->vlan_rx_register = e100_vlan_rx_register; + dev->vlan_rx_add_vid = e100_vlan_rx_add_vid; + dev->vlan_rx_kill_vid = e100_vlan_rx_kill_vid; dev->irq = pcid->irq; dev->open = &e100_open; dev->hard_start_xmit = &e100_xmit_frame; @@ -660,9 +667,11 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) dev->set_multicast_list = &e100_set_multi; dev->set_mac_address = &e100_set_mac; dev->do_ioctl = &e100_ioctl; - if (bdp->flags & USE_IPCB) { - dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; - } + + if (bdp->flags & USE_IPCB) + dev->features = NETIF_F_SG | NETIF_F_HW_CSUM | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + e100nics++; e100_get_speed_duplex_caps(bdp); @@ -1998,17 +2007,15 @@ e100_rx_srv(struct e100_private *bdp) } else { skb->ip_summed = CHECKSUM_NONE; } - switch (netif_rx(skb)) { - case NET_RX_BAD: - case NET_RX_DROP: - case NET_RX_CN_MOD: - case NET_RX_CN_HIGH: - break; - default: - bdp->drv_stats.net_stats.rx_bytes += skb->len; - break; - } + if(bdp->vlgrp && (rfd_status & CB_STATUS_VLAN)) { + vlan_hwaccel_rx(skb, bdp->vlgrp, be16_to_cpu(rfd->vlanid)); + } else { + netif_rx(skb); + } + dev->last_rx = jiffies; + bdp->drv_stats.net_stats.rx_bytes += skb->len; + rfd_cnt++; } /* end of rfd loop */ @@ -2101,6 +2108,11 @@ e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) tcb->tcbu.ipcb.ip_schedule &= ~IPCB_TCPUDP_CHECKSUM_ENABLE; } + if(bdp->vlgrp && vlan_tx_tag_present(skb)) { + (tcb->tcbu).ipcb.ip_activation_high |= IPCB_INSERTVLAN_ENABLE; + (tcb->tcbu).ipcb.vlan = cpu_to_be16(vlan_tx_tag_get(skb)); + } + tcb->tcb_hdr.cb_status = 0; tcb->tcb_thrshld = bdp->tx_thld; tcb->tcb_hdr.cb_cmd |= __constant_cpu_to_le16(CB_S_BIT); @@ -4022,6 +4034,45 @@ exit: spin_unlock_bh(&(bdp->bd_non_tx_lock)); } +static void +e100_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp) +{ + struct e100_private *bdp = netdev->priv; + + e100_disable_clear_intr(bdp); + bdp->vlgrp = grp; + + if(grp) { + /* enable VLAN tag insert/strip */ + e100_config_vlan_drop(bdp, true); + + } else { + /* disable VLAN tag insert/strip */ + e100_config_vlan_drop(bdp, false); + } + + e100_config(bdp); + e100_set_intr_mask(bdp); +} + +static void +e100_vlan_rx_add_vid(struct net_device *netdev, u16 vid) +{ + /* We don't do Vlan filtering */ + return; +} + +static void +e100_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) +{ + struct e100_private *bdp = netdev->priv; + + if(bdp->vlgrp) + bdp->vlgrp->vlan_devices[vid] = NULL; + /* We don't do Vlan filtering */ + return; +} + #ifdef CONFIG_PM static int e100_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) -- cgit v1.2.3 From ea35c57a63dc2b8b0d2d0647c4ce6e960f15274f Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:07:15 -0500 Subject: [E100] Clean up #include order On Thu, 20 Mar 2003, Scott Feldman wrote: * clean up #includes --- drivers/net/e100/e100.h | 1 + drivers/net/e100/e100_main.c | 1 - drivers/net/e100/e100_phy.h | 2 -- 3 files changed, 1 insertion(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h index 704c4c738d46..034b12c8e730 100644 --- a/drivers/net/e100/e100.h +++ b/drivers/net/e100/e100.h @@ -58,6 +58,7 @@ #include #include #include +#include #define E100_REGS_LEN 1 /* diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 47e818a8358a..6899f8c8526c 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -132,7 +132,6 @@ static char *test_strings[] = { static int e100_ethtool_led_blink(struct net_device *, struct ifreq *); -#include static int e100_mii_ioctl(struct net_device *, struct ifreq *, int); static unsigned char e100_delayed_exec_non_cu_cmd(struct e100_private *, diff --git a/drivers/net/e100/e100_phy.h b/drivers/net/e100/e100_phy.h index 9335f70a9b51..df2d483e67f8 100644 --- a/drivers/net/e100/e100_phy.h +++ b/drivers/net/e100/e100_phy.h @@ -30,8 +30,6 @@ #include "e100.h" -#include - /* * Auto-polarity enable/disable * e100_autopolarity = 0 => disable auto-polarity -- cgit v1.2.3 From 2be4a5ffc2d4e9a0a8b4b44b78f44de3ca453d04 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:07:34 -0500 Subject: [E100] Bug fix on setting up Tx csum On Thu, 20 Mar 2003, Scott Feldman wrote: * Bug fix on setting up Tx csum --- drivers/net/e100/e100_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 6899f8c8526c..39985936095d 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -2130,7 +2130,8 @@ e100_prepare_xmit_buff(struct e100_private *bdp, struct sk_buff *skb) if ((ip->protocol == IPPROTO_TCP) || (ip->protocol == IPPROTO_UDP)) { - tcb->tcbu.ipcb.ip_activation_high = + + tcb->tcbu.ipcb.ip_activation_high |= IPCB_HARDWAREPARSING_ENABLE; tcb->tcbu.ipcb.ip_schedule |= IPCB_TCPUDP_CHECKSUM_ENABLE; -- cgit v1.2.3 From 3e961093cee862e0944c6fd41084ecc6b2b26b87 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:07:58 -0500 Subject: [E100] Banish strong branding marketing strings On Thu, 20 Mar 2003, Scott Feldman wrote: * Get rid of all of the strong marketing brand strings and replace with simple pci_device_id table. pci.ids should be the master list for device ID/strings. --- drivers/net/e100/e100.h | 3 - drivers/net/e100/e100_main.c | 55 ++++---- drivers/net/e100/e100_vendor.h | 311 ----------------------------------------- 3 files changed, 29 insertions(+), 340 deletions(-) delete mode 100644 drivers/net/e100/e100_vendor.h (limited to 'drivers') diff --git a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h index 034b12c8e730..ba8e4708874e 100644 --- a/drivers/net/e100/e100.h +++ b/drivers/net/e100/e100.h @@ -889,7 +889,6 @@ struct e100_private { struct driver_stats drv_stats; u8 rev_id; /* adapter PCI revision ID */ - unsigned long device_type; /* device type from e100_vendor.h */ unsigned int phy_addr; /* address of PHY component */ unsigned int PhyId; /* ID of PHY component */ @@ -926,8 +925,6 @@ struct e100_private { struct cfg_params params; /* adapter's command line parameters */ - char *id_string; - u32 speed_duplex_caps; /* adapter's speed/duplex capabilities */ /* WOL params for ethtool */ diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 39985936095d..7fa76d9bc659 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -86,7 +86,6 @@ #include "e100_ucode.h" #include "e100_config.h" #include "e100_phy.h" -#include "e100_vendor.h" static char e100_gstrings_stats[][ETH_GSTRING_LEN] = { "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", @@ -194,7 +193,6 @@ static void e100_print_brd_conf(struct e100_private *); static void e100_set_multi(struct net_device *); void e100_set_speed_duplex(struct e100_private *); -char *e100_get_brand_msg(struct e100_private *); static u8 e100_pci_setup(struct pci_dev *, struct e100_private *); static u8 e100_sw_init(struct e100_private *); static void e100_tco_workaround(struct e100_private *); @@ -681,12 +679,10 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) memcpy(bdp->ifname, dev->name, IFNAMSIZ); bdp->ifname[IFNAMSIZ-1] = 0; - bdp->device_type = ent->driver_data; printk(KERN_NOTICE "e100: %s: %s\n", - bdp->device->name, e100_get_brand_msg(bdp)); + bdp->device->name, "Intel(R) PRO/100 Network Connection"); e100_print_brd_conf(bdp); - bdp->id_string = e100_get_brand_msg(bdp); bdp->wolsupported = 0; bdp->wolopts = 0; @@ -765,6 +761,34 @@ e100_remove1(struct pci_dev *pcid) --e100nics; } +static struct pci_device_id e100_id_table[] __devinitdata = { + {0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1051, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1052, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1054, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x1055, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, }, + {0,} /* This has to be the last entry*/ +}; MODULE_DEVICE_TABLE(pci, e100_id_table); static struct pci_driver e100_driver = { @@ -2916,27 +2940,6 @@ e100_print_brd_conf(struct e100_private *bdp) printk(KERN_NOTICE " cpu cycle saver enabled\n"); } -/** - * e100_get_brand_msg - * @bdp: atapter's private data struct - * - * This routine checks if there is specified branding message for a given board - * type and returns a pointer to the string containing the branding message. - */ -char * -e100_get_brand_msg(struct e100_private *bdp) -{ - int i; - - for (i = 0; e100_vendor_info_array[i].idstr != NULL; i++) { - if (e100_vendor_info_array[i].device_type == bdp->device_type) { - return e100_vendor_info_array[i].idstr; - } - } - - return e100_vendor_info_array[E100_ALL_BOARDS].idstr; -} - /** * e100_pci_setup - setup the adapter's PCI information * @pcid: adapter's pci_dev struct diff --git a/drivers/net/e100/e100_vendor.h b/drivers/net/e100/e100_vendor.h deleted file mode 100644 index 01be2d41b9cd..000000000000 --- a/drivers/net/e100/e100_vendor.h +++ /dev/null @@ -1,311 +0,0 @@ -/******************************************************************************* - - - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the Free - Software Foundation; either version 2 of the License, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Linux NICS - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 -*******************************************************************************/ - -#ifndef E100_VENDOR_ID_INFO -#define E100_VENDOR_ID_INFO -/* ====================================================================== */ -/* vendor_info */ -/* ====================================================================== */ - -struct e100_vendor_info { - unsigned long device_type; - char *idstr; -}; - -enum e100_device_type { - E100_BRD_100TX = 1, - E100_BRD_100T4, - E100_BRD_10T, - E100_BRD_100WFM, - E100_BRD_82557, - E100_BRD_82557_WOL, - E100_BRD_82558, - E100_BRD_82558_WOL, - E100_BRD_100, - E100_BRD_100M, - E100_BRD_AOL2, - E100_BRD_AOL, - E100_PROS_M, - E100_PROS_AM, - E100_PROS_AM_AOL, - E100_PROS_DT, - E100_PRO_DT, - E100_PROM_DT, - E100_PRO_SRV, - E100_PRO_SRVP, - E100_PROS_SRV, - E100_PRO_DUAL, - E100_PROS_DUAL, - E100_PROP_DUAL, - E100_PROP_WOL, - E100_PROS_MOB, - E100_PRO_CB, - E100_PRO_CB_M, - E100_PROSR_MOB, - E100_PROS_MC, - E100_PROSR_MC, - E100_PROP_MC, - E100_PROSP_MC, - E100_PROP_MOB, - E100_PROSP_MOB, - E100_PRO_MINI, - E100_PRO_NET, - E100_PROS_NET, - E100_PROVM_NET, - E100_PROVE_D, - E100_82559_LOM, - E100_82559_LOM_AOL, - E100_82559_LOM_AOL2, - E100_82559_LOM_DELL, - E100_IBM_MDS, - E100_CMPQ_S, - E100_PROVE_DA, - E100_PROVM_DA, - E100_PROVE_LOM, - E100_PROVE_NET, - E100_82562, - E100_82551QM, - E100_ALL_BOARDS -}; - -struct e100_vendor_info e100_vendor_info_array[] = { - { E100_BRD_100TX, "Intel(R) PRO/100B PCI Adapter (TX)"}, - { E100_BRD_100T4, "Intel(R) PRO/100B PCI Adapter (T4)"}, - { E100_BRD_10T, "Intel(R) PRO/10+ PCI Adapter"}, - { E100_BRD_100WFM, "Intel(R) PRO/100 WfM PCI Adapter"}, - { E100_BRD_82557, "Intel(R) 82557-based Integrated Ethernet PCI (10/100)"}, - { E100_BRD_82557_WOL, "Intel(R) 82557-based Integrated Ethernet with Wake on LAN*"}, - { E100_BRD_82558, "Intel(R) 82558-based Integrated Ethernet"}, - { E100_BRD_82558_WOL, "Intel(R) 82558-based Integrated Ethernet with Wake on LAN*"}, - { E100_BRD_100, "Intel(R) PRO/100+ PCI Adapter"}, - { E100_BRD_100M, "Intel(R) PRO/100+ Management Adapter"}, - { E100_BRD_AOL2, "Intel(R) PRO/100+ Alert on LAN* 2 Management Adapter"}, - { E100_82559_LOM_DELL, "Intel(R) 8255x Based Network Connection"}, - { E100_BRD_AOL, "Intel(R) PRO/100+ Alert on LAN* Management Adapter"}, - { E100_PROS_M, "Intel(R) PRO/100 S Management Adapter"}, - { E100_PROS_AM, "Intel(R) PRO/100 S Advanced Management Adapter"}, - { E100_PROS_AM_AOL, "Intel(R) PRO/100+ Management Adapter with Alert On LAN* GC"}, - { E100_PROS_DT, "Intel(R) PRO/100 S Desktop Adapter"}, - { E100_PRO_DT, "Intel(R) PRO/100 Desktop Adapter"}, - { E100_PROM_DT, "Intel(R) PRO/100 M Desktop Adapter"}, - { E100_PRO_SRV, "Intel(R) PRO/100+ Server Adapter"}, - { E100_PRO_SRVP, "Intel(R) PRO/100+ Server Adapter (PILA8470B)"}, - { E100_PROS_SRV, "Intel(R) PRO/100 S Server Adapter"}, - { E100_PRO_DUAL, "Intel(R) PRO/100 Dual Port Server Adapter"}, - { E100_PROS_DUAL, "Intel(R) PRO/100 S Dual Port Server Adapter"}, - { E100_PROP_DUAL, "Intel(R) PRO/100+ Dual Port Server Adapter"}, - { E100_PROP_WOL, "Intel(R) PRO/100+ Management Adapter with Alert On LAN* G Server"}, - { E100_PROS_MOB, "Intel(R) PRO/100 S Mobile Adapter"}, - { E100_PRO_CB, "Intel(R) PRO/100 CardBus II"}, - { E100_PRO_CB_M, "Intel(R) PRO/100 LAN+Modem56 CardBus II"}, - { E100_PROSR_MOB, "Intel(R) PRO/100 SR Mobile Adapter"}, - { E100_PROS_MC, "Intel(R) PRO/100 S Mobile Combo Adapter"}, - { E100_PROSR_MC, "Intel(R) PRO/100 SR Mobile Combo Adapter"}, - { E100_PROP_MC, "Intel(R) PRO/100 P Mobile Combo Adapter"}, - { E100_PROSP_MC, "Intel(R) PRO/100 SP Mobile Combo Adapter"}, - { E100_PROP_MOB, "Intel(R) PRO/100 P Mobile Adapter"}, - { E100_PROSP_MOB, "Intel(R) PRO/100 SP Mobile Adapter"}, - { E100_PRO_MINI, "Intel(R) PRO/100+ Mini PCI"}, - { E100_PRO_NET, "Intel(R) PRO/100 Network Connection" }, - { E100_PROS_NET, "Intel(R) PRO/100 S Network Connection" }, - { E100_PROVM_NET, "Intel(R) PRO/100 VM Network Connection"}, - { E100_PROVE_D, "Intel(R) PRO/100 VE Desktop Connection"}, - { E100_82559_LOM, "Intel(R) 82559 Fast Ethernet LAN on Motherboard"}, - { E100_82559_LOM_AOL, "Intel(R) 82559 Fast Ethernet LOM with Alert on LAN*" }, - { E100_82559_LOM_AOL2, "Intel(R) 82559 Fast Ethernet LOM with Alert on LAN* 2" }, - { E100_IBM_MDS, "IBM Mobile, Desktop & Server Adapters"}, - { E100_CMPQ_S, "Compaq Fast Ethernet Server Adapter" }, - { E100_PROVE_DA, "Intel(R) PRO/100 VE Desktop Adapter"}, - { E100_PROVM_DA, "Intel(R) PRO/100 VM Desktop Adapter"}, - { E100_PROVE_LOM, "Intel(R) PRO/100 VE Network ConnectionPLC LOM" }, - { E100_PROVE_NET, "Intel(R) PRO/100 VE Network Connection"}, - { E100_82562, "Intel(R)82562 based Fast Ethernet Connection"}, - { E100_82551QM, "Intel(R) PRO/100 M Mobile Connection"}, - { E100_ALL_BOARDS, "Intel(R) 8255x-based Ethernet Adapter"}, - {0,NULL} -}; - -static struct pci_device_id e100_id_table[] __devinitdata = { - {0x8086, 0x1229, 0x8086, 0x0001, 0, 0, E100_BRD_100TX}, - {0x8086, 0x1229, 0x8086, 0x0002, 0, 0, E100_BRD_100T4}, - {0x8086, 0x1229, 0x8086, 0x0003, 0, 0, E100_BRD_10T}, - {0x8086, 0x1229, 0x8086, 0x0004, 0, 0, E100_BRD_100WFM}, - {0x8086, 0x1229, 0x8086, 0x0005, 0, 0, E100_BRD_82557}, - {0x8086, 0x1229, 0x8086, 0x0006, 0, 0, E100_BRD_82557_WOL}, - {0x8086, 0x1229, 0x8086, 0x0002, 0, 0, E100_BRD_100T4}, - {0x8086, 0x1229, 0x8086, 0x0003, 0, 0, E100_BRD_10T}, - {0x8086, 0x1229, 0x8086, 0x0004, 0, 0, E100_BRD_100WFM}, - {0x8086, 0x1229, 0x8086, 0x0005, 0, 0, E100_BRD_82557}, - {0x8086, 0x1229, 0x8086, 0x0006, 0, 0, E100_BRD_82557_WOL}, - {0x8086, 0x1229, 0x8086, 0x0007, 0, 0, E100_BRD_82558}, - {0x8086, 0x1229, 0x8086, 0x0008, 0, 0, E100_BRD_82558_WOL}, - {0x8086, 0x1229, 0x8086, 0x0009, 0, 0, E100_BRD_100}, - {0x8086, 0x1229, 0x8086, 0x000A, 0, 0, E100_BRD_100M}, - {0x8086, 0x1229, 0x8086, 0x000B, 0, 0, E100_BRD_100}, - {0x8086, 0x1229, 0x8086, 0x000C, 0, 0, E100_BRD_100M}, - {0x8086, 0x1229, 0x8086, 0x000D, 0, 0, E100_BRD_AOL2}, - {0x8086, 0x1229, 0x8086, 0x000E, 0, 0, E100_BRD_AOL}, - {0x8086, 0x1229, 0x8086, 0x0010, 0, 0, E100_PROS_M}, - {0x8086, 0x1229, 0x8086, 0x0011, 0, 0, E100_PROS_M}, - {0x8086, 0x1229, 0x8086, 0x0012, 0, 0, E100_PROS_AM}, - {0x8086, 0x1229, 0x8086, 0x0013, 0, 0, E100_PROS_AM}, - {0x8086, 0x1229, 0x8086, 0x0030, 0, 0, E100_PROS_AM_AOL}, - {0x8086, 0x1229, 0x8086, 0x0040, 0, 0, E100_PROS_DT}, - {0x8086, 0x1229, 0x8086, 0x0041, 0, 0, E100_PROS_DT}, - {0x8086, 0x1229, 0x8086, 0x0042, 0, 0, E100_PRO_DT}, - {0x8086, 0x1229, 0x8086, 0x0050, 0, 0, E100_PROS_DT}, - {0x8086, 0x1229, 0x8086, 0x0070, 0, 0, E100_PROM_DT}, - {0x8086, 0x1229, 0x8086, 0x1009, 0, 0, E100_PRO_SRV}, - {0x8086, 0x1229, 0x8086, 0x100C, 0, 0, E100_PRO_SRVP}, - {0x8086, 0x1229, 0x8086, 0x1012, 0, 0, E100_PROS_SRV}, - {0x8086, 0x1229, 0x8086, 0x1013, 0, 0, E100_PROS_SRV}, - {0x8086, 0x1229, 0x8086, 0x1014, 0, 0, E100_PRO_DUAL}, - {0x8086, 0x1229, 0x8086, 0x1015, 0, 0, E100_PROS_DUAL}, - {0x8086, 0x1229, 0x8086, 0x1016, 0, 0, E100_PROS_DUAL}, - {0x8086, 0x1229, 0x8086, 0x1017, 0, 0, E100_PROP_DUAL}, - {0x8086, 0x1229, 0x8086, 0x1030, 0, 0, E100_PROP_WOL}, - {0x8086, 0x1229, 0x8086, 0x1040, 0, 0, E100_PROS_SRV}, - {0x8086, 0x1229, 0x8086, 0x1041, 0, 0, E100_PROS_SRV}, - {0x8086, 0x1229, 0x8086, 0x1042, 0, 0, E100_PRO_SRV}, - {0x8086, 0x1229, 0x8086, 0x1050, 0, 0, E100_PROS_SRV}, - {0x8086, 0x1229, 0x8086, 0x10F0, 0, 0, E100_PROP_DUAL}, - {0x8086, 0x1229, 0x8086, 0x10F0, 0, 0, E100_PROP_DUAL}, - {0x8086, 0x1229, 0x8086, 0x2009, 0, 0, E100_PROS_MOB}, - {0x8086, 0x1229, 0x8086, 0x200D, 0, 0, E100_PRO_CB}, - {0x8086, 0x1229, 0x8086, 0x200E, 0, 0, E100_PRO_CB_M}, - {0x8086, 0x1229, 0x8086, 0x200F, 0, 0, E100_PROSR_MOB}, - {0x8086, 0x1229, 0x8086, 0x2010, 0, 0, E100_PROS_MC}, - {0x8086, 0x1229, 0x8086, 0x2013, 0, 0, E100_PROSR_MC}, - {0x8086, 0x1229, 0x8086, 0x2016, 0, 0, E100_PROS_MOB}, - {0x8086, 0x1229, 0x8086, 0x2017, 0, 0, E100_PROS_MC}, - {0x8086, 0x1229, 0x8086, 0x2018, 0, 0, E100_PROSR_MOB}, - {0x8086, 0x1229, 0x8086, 0x2019, 0, 0, E100_PROSR_MC}, - {0x8086, 0x1229, 0x8086, 0x2101, 0, 0, E100_PROP_MOB}, - {0x8086, 0x1229, 0x8086, 0x2102, 0, 0, E100_PROSP_MOB}, - {0x8086, 0x1229, 0x8086, 0x2103, 0, 0, E100_PROSP_MOB}, - {0x8086, 0x1229, 0x8086, 0x2104, 0, 0, E100_PROSP_MOB}, - {0x8086, 0x1229, 0x8086, 0x2105, 0, 0, E100_PROSP_MOB}, - {0x8086, 0x1229, 0x8086, 0x2106, 0, 0, E100_PROP_MOB}, - {0x8086, 0x1229, 0x8086, 0x2107, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x8086, 0x2108, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x8086, 0x2200, 0, 0, E100_PROP_MC}, - {0x8086, 0x1229, 0x8086, 0x2201, 0, 0, E100_PROP_MC}, - {0x8086, 0x1229, 0x8086, 0x2202, 0, 0, E100_PROSP_MC}, - {0x8086, 0x1229, 0x8086, 0x2203, 0, 0, E100_PRO_MINI}, - {0x8086, 0x1229, 0x8086, 0x2204, 0, 0, E100_PRO_MINI}, - {0x8086, 0x1229, 0x8086, 0x2205, 0, 0, E100_PROSP_MC}, - {0x8086, 0x1229, 0x8086, 0x2206, 0, 0, E100_PROSP_MC}, - {0x8086, 0x1229, 0x8086, 0x2207, 0, 0, E100_PROSP_MC}, - {0x8086, 0x1229, 0x8086, 0x2208, 0, 0, E100_PROP_MC}, - {0x8086, 0x1229, 0x8086, 0x2408, 0, 0, E100_PRO_MINI}, - {0x8086, 0x1229, 0x8086, 0x240F, 0, 0, E100_PRO_MINI}, - {0x8086, 0x1229, 0x8086, 0x2411, 0, 0, E100_PRO_MINI}, - {0x8086, 0x1229, 0x8086, 0x3400, 0, 0, E100_82559_LOM}, - {0x8086, 0x1229, 0x8086, 0x3000, 0, 0, E100_82559_LOM}, - {0x8086, 0x1229, 0x8086, 0x3001, 0, 0, E100_82559_LOM_AOL}, - {0x8086, 0x1229, 0x8086, 0x3002, 0, 0, E100_82559_LOM_AOL2}, - {0x8086, 0x1229, 0x8086, 0x3006, 0, 0, E100_PROS_NET}, - {0x8086, 0x1229, 0x8086, 0x3007, 0, 0, E100_PROS_NET}, - {0x8086, 0x1229, 0x8086, 0x3008, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x8086, 0x3010, 0, 0, E100_PROS_NET}, - {0x8086, 0x1229, 0x8086, 0x3011, 0, 0, E100_PROS_NET}, - {0x8086, 0x1229, 0x8086, 0x3012, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x005C, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x305C, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x405C, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x605C, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x505C, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x105C, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x805C, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x705C, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x01F1, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x0232, 0, 0, E100_IBM_MDS}, - {0x8086, 0x1229, 0x1014, 0x0207, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x023F, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x01BC, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x01CE, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x01DC, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x01EB, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x01EC, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x0202, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x0205, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x1014, 0x0217, 0, 0, E100_PRO_NET}, - {0x8086, 0x1229, 0x0E11, 0xB01E, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB02F, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB04A, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB0C6, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB0C7, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB0D7, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB0DD, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB0DE, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB0E1, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB134, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB13C, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB144, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB163, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x0E11, 0xB164, 0, 0, E100_CMPQ_S}, - {0x8086, 0x1229, 0x1028, PCI_ANY_ID, 0, 0, E100_82559_LOM_DELL}, - {0x8086, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, - - {0x8086, 0x2449, 0x1014, 0x0265, 0, 0, E100_PROVE_D}, - {0x8086, 0x2449, 0x1014, 0x0267, 0, 0, E100_PROVE_D}, - {0x8086, 0x2449, 0x1014, 0x026A, 0, 0, E100_PROVE_D}, - {0x8086, 0x2449, 0x8086, 0x3010, 0, 0, E100_PROVE_DA}, - {0x8086, 0x2449, 0x8086, 0x3011, 0, 0, E100_PROVM_DA}, - {0x8086, 0x2449, 0x8086, 0x3013, 0, 0, E100_PROVE_NET}, - {0x8086, 0x2449, 0x8086, 0x3014, 0, 0, E100_PROVM_NET}, - {0x8086, 0x2449, 0x8086, 0x3016, 0, 0, E100_PROP_MC}, - {0x8086, 0x2449, 0x8086, 0x3017, 0, 0, E100_PROP_MOB}, - {0x8086, 0x2449, 0x8086, 0x3018, 0, 0, E100_PRO_NET}, - {0x8086, 0x2449, 0x0E11, PCI_ANY_ID, 0, 0, E100_PROVM_NET}, - {0x8086, 0x2449, 0x1014, PCI_ANY_ID, 0, 0, E100_PROVE_D}, - {0x8086, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, - - {0x8086, 0x1059, 0x1179, 0x0005, 0, 0, E100_82551QM}, - {0x8086, 0x1059, 0x1033, 0x8191, 0, 0, E100_82551QM}, - {0x8086, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_82551QM}, - - {0x8086, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, - {0x8086, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, - {0x8086, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_ALL_BOARDS}, - {0x8086, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET}, - {0x8086, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET}, - {0x8086, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET}, - {0x8086, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET}, - {0x8086, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET}, - {0x8086, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET}, - {0x8086, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET}, - {0x8086, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET}, - {0x8086, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET}, - {0x8086, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVE_NET}, - {0x8086, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_PROVM_NET}, - {0x8086, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_82562}, - {0x8086, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, E100_82562}, - {0,} /* This has to be the last entry*/ -}; - -#endif /* E100_VENDOR_ID_INFO */ -- cgit v1.2.3 From d3fe58910590c5ebce03557d2ebc1c0ec33e783c Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:08:16 -0500 Subject: [E100] forced speed/duplex link recover On Thu, 20 Mar 2003, Scott Feldman wrote: * Bug fix when changing to non-autoneg, device may lose link with some switches, so try to recover link by forcing PHY. --- drivers/net/e100/e100_main.c | 16 ++++++++++++++-- drivers/net/e100/e100_phy.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 7fa76d9bc659..a644a26b6cef 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -87,6 +87,8 @@ #include "e100_config.h" #include "e100_phy.h" +extern void e100_force_speed_duplex_to_phy(struct e100_private *bdp); + static char e100_gstrings_stats[][ETH_GSTRING_LEN] = { "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", @@ -1707,6 +1709,11 @@ e100_watchdog(struct net_device *dev) } else { if (netif_running(dev)) netif_stop_queue(dev); + /* When changing to non-autoneg, device may lose */ + /* link with some switches. e100 will try to */ + /* revover link by sending command to PHY layer */ + if (bdp->params.e100_speed_duplex != E100_AUTONEG) + e100_force_speed_duplex_to_phy(bdp); } rmb(); @@ -3023,12 +3030,17 @@ e100_isolate_driver(struct e100_private *bdp) void e100_set_speed_duplex(struct e100_private *bdp) { - if (netif_carrier_ok(bdp->device)) + int carrier_ok; + /* Device may lose link with some siwtches when */ + /* changing speed/duplex to non-autoneg. e100 */ + /* needs to remember carrier state in order to */ + /* start watchdog timer for recovering link */ + if ((carrier_ok = netif_carrier_ok(bdp->device))) e100_isolate_driver(bdp); e100_phy_set_speed_duplex(bdp, true); e100_config_fc(bdp); /* re-config flow-control if necessary */ e100_config(bdp); - if (netif_carrier_ok(bdp->device)) + if (carrier_ok) e100_deisolate_driver(bdp, false); } diff --git a/drivers/net/e100/e100_phy.c b/drivers/net/e100/e100_phy.c index 4f291584b53e..08782934bdf6 100644 --- a/drivers/net/e100/e100_phy.c +++ b/drivers/net/e100/e100_phy.c @@ -636,7 +636,6 @@ e100_force_speed_duplex(struct e100_private *bdp) control &= ~BMCR_ANENABLE; control &= ~BMCR_LOOPBACK; - /* Check e100.c values */ switch (bdp->params.e100_speed_duplex) { case E100_SPEED_10_HALF: control &= ~BMCR_SPEED100; @@ -682,6 +681,41 @@ e100_force_speed_duplex(struct e100_private *bdp) } while (true); } +void +e100_force_speed_duplex_to_phy(struct e100_private *bdp) +{ + u16 control; + + e100_mdi_read(bdp, MII_BMCR, bdp->phy_addr, &control); + control &= ~BMCR_ANENABLE; + control &= ~BMCR_LOOPBACK; + + switch (bdp->params.e100_speed_duplex) { + case E100_SPEED_10_HALF: + control &= ~BMCR_SPEED100; + control &= ~BMCR_FULLDPLX; + break; + + case E100_SPEED_10_FULL: + control &= ~BMCR_SPEED100; + control |= BMCR_FULLDPLX; + break; + + case E100_SPEED_100_HALF: + control |= BMCR_SPEED100; + control &= ~BMCR_FULLDPLX; + break; + + case E100_SPEED_100_FULL: + control |= BMCR_SPEED100; + control |= BMCR_FULLDPLX; + break; + } + + /* Send speed/duplex command to PHY layer. */ + e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr, control); +} + /* * Procedure: e100_set_fc * -- cgit v1.2.3 From 6e8409547b1d9b26f5a95e9a82cba19d83ae83f6 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:08:35 -0500 Subject: [E100] ICH5 support added On Thu, 20 Mar 2003, Scott Feldman wrote: * ICH5 support: chipset integrated LAN (8255x) * PHY loopback diags is broken on all ICHs --- drivers/net/e100/e100_main.c | 4 +++- drivers/net/e100/e100_test.c | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index a644a26b6cef..1b427d1fa07e 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -615,7 +615,9 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) } if (((bdp->pdev->device > 0x1030) - && (bdp->pdev->device < 0x103F)) + && (bdp->pdev->device < 0x103F)) + || ((bdp->pdev->device >= 0x1050) + && (bdp->pdev->device <= 0x1057)) || (bdp->pdev->device == 0x2449) || (bdp->pdev->device == 0x2459) || (bdp->pdev->device == 0x245D)) { diff --git a/drivers/net/e100/e100_test.c b/drivers/net/e100/e100_test.c index 147ce34731bc..0ff7266ef8e2 100644 --- a/drivers/net/e100/e100_test.c +++ b/drivers/net/e100/e100_test.c @@ -242,6 +242,9 @@ e100_diag_config_loopback(struct e100_private* bdp, *dynamic_tbd = e100_config_dynamic_tbd(bdp,*dynamic_tbd); if (set_loopback) { + /* ICH PHY loopback is broken */ + if (bdp->flags & IS_ICH && loopback_mode == PHY_LOOPBACK) + loopback_mode = MAC_LOOPBACK; /* Configure loopback on MAC */ e100_config_loopback_mode(bdp,loopback_mode); } else { -- cgit v1.2.3 From 3cde612480d198463ff50a63bc89b205c8251a4d Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:08:55 -0500 Subject: [E100] Honor WOL settings in EEPROM On Thu, 20 Mar 2003, Scott Feldman wrote: * Honor WOL settings in EEPROM: only advertise WOL magic packet if in EEPROM. --- drivers/net/e100/e100_main.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index 1b427d1fa07e..cb8c670cbeab 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -693,13 +693,14 @@ e100_found1(struct pci_dev *pcid, const struct pci_device_id *ent) /* Check if WoL is enabled on EEPROM */ if (e100_eeprom_read(bdp, EEPROM_ID_WORD) & BIT_5) { + /* Magic Packet WoL is enabled on device by default */ + /* if EEPROM WoL bit is TRUE */ + bdp->wolsupported = WAKE_MAGIC; + bdp->wolopts = WAKE_MAGIC; if (bdp->rev_id >= D101A4_REV_ID) bdp->wolsupported = WAKE_PHY | WAKE_MAGIC; if (bdp->rev_id >= D101MA_REV_ID) bdp->wolsupported |= WAKE_UCAST | WAKE_ARP; - /* Magic Packet WoL is enabled on device by default */ - /* if EEPROM WoL bit is TRUE */ - bdp->wolopts = WAKE_MAGIC; } printk(KERN_NOTICE "\n"); -- cgit v1.2.3 From ca1a0f0777fbce3d1cafe097653ab5b6f224a1dd Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:09:13 -0500 Subject: [E100] interrupt handler free fix On Thu, 20 Mar 2003, Scott Feldman wrote: * Bug fix on e100_close when repeating hot remove/hot add from team. Basically need to disable interurpts and unregister handler before shutting h/w down. * Need to mask only the relevant bits in the interrupt status register --- drivers/net/e100/e100_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index cb8c670cbeab..d37e2ed96448 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -1036,13 +1036,14 @@ e100_close(struct net_device *dev) { struct e100_private *bdp = dev->priv; + e100_disable_clear_intr(bdp); + free_irq(dev->irq, dev); bdp->intr_mask = SCB_INT_MASK; e100_isolate_driver(bdp); netif_carrier_off(bdp->device); bdp->cur_line_speed = 0; bdp->cur_dplx_mode = 0; - free_irq(dev->irq, dev); e100_clear_pools(bdp); return 0; @@ -1840,7 +1841,8 @@ e100intr(int irq, void *dev_inst, struct pt_regs *regs) bdp = dev->priv; intr_status = readw(&bdp->scb->scb_status); - if (!intr_status || (intr_status == 0xffff)) { + /* If not my interrupt, just return */ + if (!(intr_status & SCB_STATUS_ACK_MASK) || (intr_status == 0xffff)) { return; } -- cgit v1.2.3 From 6233d7e08c8803fd4a1adcb1aafce3c14e36f115 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:09:31 -0500 Subject: [E100] Validate updates to MAC address On Thu, 20 Mar 2003, Scott Feldman wrote: * Validate updates to MAC address as valid ethernet address. --- drivers/net/e100/e100_main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index d37e2ed96448..f304d3802df5 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -1140,6 +1140,8 @@ e100_set_mac(struct net_device *dev, void *addr) int rc = -1; struct sockaddr *p_sockaddr = (struct sockaddr *) addr; + if (!is_valid_ether_addr(p_sockaddr->sa_data)) + return -EADDRNOTAVAIL; bdp = dev->priv; if (e100_setup_iaaddr(bdp, (u8 *) (p_sockaddr->sa_data))) { @@ -1274,6 +1276,10 @@ e100_init(struct e100_private *bdp) /* read the MAC address from the eprom */ e100_rd_eaddr(bdp); + if (!is_valid_ether_addr(bdp->device->dev_addr)) { + printk(KERN_ERR "e100: Invalid Ethernet address\n"); + return false; + } /* read NIC's part number */ e100_rd_pwa_no(bdp); -- cgit v1.2.3 From e88513602df1e22740073cd89ebb723cf283dfda Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:09:50 -0500 Subject: [E100] ethtool EEPROM and GSTRING fixes On Thu, 20 Mar 2003, Scott Feldman wrote: * Bug fix: read wrong byte in EEPROM when offset is odd number * Bug fix: memory leak in ETHTOOL_GSTRINGS [Oleg Drokin ifr_data, &ecmd, sizeof (ecmd))) return -EFAULT; - if (copy_to_user(usr_eeprom_ptr, eeprom_data, ecmd.len)) + if(ecmd.offset & 1) + eeprom_data_bytes++; + if (copy_to_user(usr_eeprom_ptr, eeprom_data_bytes, ecmd.len)) return -EFAULT; } else { if (ecmd.magic != E100_EEPROM_MAGIC) @@ -3796,7 +3799,8 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) return -EFAULT; switch (info.string_set) { - case ETH_SS_TEST: + case ETH_SS_TEST: { + int ret = 0; if (info.len > E100_MAX_TEST_RES) info.len = E100_MAX_TEST_RES; strings = kmalloc(info.len * ETH_GSTRING_LEN, GFP_ATOMIC); @@ -3808,7 +3812,13 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) sprintf(strings + i * ETH_GSTRING_LEN, "%-31s", test_strings[i]); } - break; + if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) + ret = -EFAULT; + if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) + ret = -EFAULT; + kfree(strings); + return ret; + } case ETH_SS_STATS: { char *strings = NULL; void *addr = ifr->ifr_data; @@ -3825,15 +3835,6 @@ static int e100_ethtool_gstrings(struct net_device *dev, struct ifreq *ifr) default: return -EOPNOTSUPP; } - - if (copy_to_user(ifr->ifr_data, &info, sizeof (info))) - return -EFAULT; - - if (copy_to_user(usr_strings, strings, info.len * ETH_GSTRING_LEN)) - return -EFAULT; - - kfree(strings); - return 0; } static int -- cgit v1.2.3 From b65f28bed889757c03a5d3b9efddb077cf9c56b3 Mon Sep 17 00:00:00 2001 From: Scott Feldman Date: Thu, 20 Mar 2003 12:10:09 -0500 Subject: [E100] ASF wakeup enabled, but only if set in EEPROM On Thu, 20 Mar 2003, Scott Feldman wrote: * Check if ASF is enabled in EEPROM, and if so, enable PME wakeup when suspending. --- drivers/net/e100/e100.h | 5 +++++ drivers/net/e100/e100_main.c | 28 +++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h index ba8e4708874e..aa58407de02d 100644 --- a/drivers/net/e100/e100.h +++ b/drivers/net/e100/e100.h @@ -303,6 +303,9 @@ struct driver_stats { /* EEPROM bit definitions */ /*- EEPROM control register bits */ +#define EEPROM_FLAG_ASF 0x8000 +#define EEPROM_FLAG_GCL 0x4000 + #define EN_TRNF 0x10 /* Enable turnoff */ #define EEDO 0x08 /* EEPROM data out */ #define EEDI 0x04 /* EEPROM data in (set for writing data) */ @@ -321,6 +324,8 @@ struct driver_stats { #define EEPROM_COMPATIBILITY_WORD 3 #define EEPROM_PWA_NO 8 #define EEPROM_ID_WORD 0x0A +#define EEPROM_CONFIG_ASF 0x0D +#define EEPROM_SMBUS_ADDR 0x90 #define EEPROM_SUM 0xbaba diff --git a/drivers/net/e100/e100_main.c b/drivers/net/e100/e100_main.c index b9b8713e28f6..d241eaa64e2e 100644 --- a/drivers/net/e100/e100_main.c +++ b/drivers/net/e100/e100_main.c @@ -228,6 +228,7 @@ static void e100_set_bool_option(struct e100_private *bdp, int, u32, int, char *); unsigned char e100_wait_exec_cmplx(struct e100_private *, u32, u8, u8); void e100_exec_cmplx(struct e100_private *, u32, u8); +static unsigned char e100_asf_enabled(struct e100_private *bdp); /** * e100_get_rx_struct - retrieve cell to hold skb buff from the pool @@ -4135,7 +4136,7 @@ e100_suspend(struct pci_dev *pcid, u32 state) e100_do_wol(pcid, bdp); /* If wol is enabled */ - if (bdp->wolopts) { + if (bdp->wolopts || e100_asf_enabled(bdp)) { pci_enable_wake(pcid, 3, 1); /* Enable PME for power state D3 */ pci_set_power_state(pcid, 3); /* Set power state to D3. */ } else { @@ -4163,6 +4164,31 @@ e100_resume(struct pci_dev *pcid) } #endif /* CONFIG_PM */ +/** + * e100_asf_enabled - checks if ASF is configured on the current adaper + * by reading registers 0xD and 0x90 in the EEPROM + * @bdp: atapter's private data struct + * + * Returns: true if ASF is enabled + */ +static unsigned char +e100_asf_enabled(struct e100_private *bdp) +{ + u16 asf_reg; + u16 smbus_addr_reg; + if ((bdp->pdev->device >= 0x1050) && (bdp->pdev->device <= 0x1055)) { + asf_reg = e100_eeprom_read(bdp, EEPROM_CONFIG_ASF); + if ((asf_reg & EEPROM_FLAG_ASF) + && !(asf_reg & EEPROM_FLAG_GCL)) { + smbus_addr_reg = + e100_eeprom_read(bdp, EEPROM_SMBUS_ADDR); + if ((smbus_addr_reg & 0xFF) != 0xFE) + return true; + } + } + return false; +} + #ifdef E100_CU_DEBUG unsigned char e100_cu_unknown_state(struct e100_private *bdp) -- cgit v1.2.3 From 605cafbe59d468503cd0756aa4daa6f129cb4de9 Mon Sep 17 00:00:00 2001 From: Osamu Tomita Date: Thu, 20 Mar 2003 13:08:10 -0500 Subject: [PATCH] Support PC-9800 subarchitecture (9/14) NIC This is the patch to support NEC PC-9800 subarchitecture against 2.5.65-ac1. (9/14) C-bus(PC98's legacy bus like ISA) network cards support. Change IO port and IRQ assign. Add NE2000 compatible driver for PC-9800. PCI netwwork card works fine without patch. Regards, Osamu Tomita --- drivers/net/3c509.c | 44 ++- drivers/net/8390.h | 3 +- drivers/net/Kconfig | 55 ++- drivers/net/Makefile | 1 + drivers/net/Makefile.lib | 1 + drivers/net/Space.c | 2 +- drivers/net/at1700.c | 120 ++++++- drivers/net/ne2k_cbus.c | 879 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ne2k_cbus.h | 481 ++++++++++++++++++++++++++ 9 files changed, 1557 insertions(+), 29 deletions(-) create mode 100644 drivers/net/ne2k_cbus.c create mode 100644 drivers/net/ne2k_cbus.h (limited to 'drivers') diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index fa7af13f3ed4..2f1d8eda388f 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c @@ -56,6 +56,10 @@ v1.19b 08Nov2002 Marc Zyngier - Introduce driver model for EISA cards. */ +/* + FIXES for PC-9800: + Shu Iwanaga: 3c569B(PC-9801 C-bus) support +*/ #define DRV_NAME "3c509" #define DRV_VERSION "1.19b" @@ -257,7 +261,7 @@ static struct mca_driver el3_mca_driver = { }; #endif /* CONFIG_MCA */ -#ifdef __ISAPNP__ +#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) static struct isapnp_device_id el3_isapnp_adapters[] __initdata = { { ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('T', 'C', 'M'), ISAPNP_FUNCTION(0x5090), @@ -350,7 +354,7 @@ static void el3_common_remove (struct net_device *dev) if (lp->pmdev) pm_unregister(lp->pmdev); #endif -#ifdef __ISAPNP__ +#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) if (lp->type == EL3_PNP) pnp_device_detach(to_pnp_dev(lp->dev)); #endif @@ -368,12 +372,12 @@ static int __init el3_probe(int card_idx) int ioaddr, irq, if_port; u16 phys_addr[3]; static int current_tag; -#ifdef __ISAPNP__ +#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) static int pnp_cards; struct pnp_dev *idev = NULL; #endif /* __ISAPNP__ */ -#ifdef __ISAPNP__ +#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) if (nopnp == 1) goto no_pnp; @@ -421,6 +425,9 @@ static int __init el3_probe(int card_idx) no_pnp: #endif /* __ISAPNP__ */ +#ifdef CONFIG_X86_PC9800 + id_port = 0x71d0; +#else /* Select an open I/O location at 0x1*0 to do contention select. */ for ( ; id_port < 0x200; id_port += 0x10) { if (check_region(id_port, 1)) @@ -435,6 +442,7 @@ no_pnp: printk(" WARNING: No I/O port available for 3c509 activation.\n"); return -ENODEV; } +#endif /* CONFIG_X86_PC9800 */ /* Next check for all ISA bus boards by sending the ID sequence to the ID_PORT. We find cards past the first by setting the 'current_tag' on cards as they are found. Cards with their tag set will not @@ -465,7 +473,7 @@ no_pnp: phys_addr[i] = htons(id_read_eeprom(i)); } -#ifdef __ISAPNP__ +#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) if (nopnp == 0) { /* The ISA PnP 3c509 cards respond to the ID sequence. This check is needed in order not to register them twice. */ @@ -490,9 +498,19 @@ no_pnp: { unsigned int iobase = id_read_eeprom(8); if_port = iobase >> 14; +#ifdef CONFIG_X86_PC9800 + ioaddr = 0x40d0 + ((iobase & 0x1f) << 8); +#else ioaddr = 0x200 + ((iobase & 0x1f) << 4); +#endif } irq = id_read_eeprom(9) >> 12; +#ifdef CONFIG_X86_PC9800 + if (irq == 7) + irq = 6; + else if (irq == 15) + irq = 13; +#endif if (!(dev = init_etherdev(NULL, sizeof(struct el3_private)))) return -ENOMEM; @@ -522,7 +540,11 @@ no_pnp: outb(0xd0 + ++current_tag, id_port); /* Activate the adaptor at the EEPROM location. */ +#ifdef CONFIG_X86_PC9800 + outb((ioaddr >> 8) | 0xe0, id_port); +#else outb((ioaddr >> 4) | 0xe0, id_port); +#endif EL3WINDOW(0); if (inw(ioaddr) != 0x6d50) { @@ -534,7 +556,7 @@ no_pnp: /* Free the interrupt so that some other card can use it. */ outw(0x0f00, ioaddr + WN0_IRQ); -#ifdef __ISAPNP__ +#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) found: /* PNP jumps here... */ #endif /* __ISAPNP__ */ @@ -543,7 +565,7 @@ no_pnp: dev->irq = irq; dev->if_port = if_port; lp = dev->priv; -#ifdef __ISAPNP__ +#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) lp->dev = &idev->dev; #endif @@ -1388,6 +1410,12 @@ el3_up(struct net_device *dev) outw(0x0001, ioaddr + 4); /* Set the IRQ line. */ +#ifdef CONFIG_X86_PC9800 + if (dev->irq == 6) + dev->irq = 7; + else if (dev->irq == 13) + dev->irq = 15; +#endif outw((dev->irq << 12) | 0x0f00, ioaddr + WN0_IRQ); /* Set the station address in window 2 each time opened. */ @@ -1550,7 +1578,7 @@ MODULE_PARM_DESC(debug, "debug level (0-6)"); MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); MODULE_PARM_DESC(xcvr,"transceiver(s) (0=internal, 1=external)"); MODULE_PARM_DESC(max_interrupt_work, "maximum events handled per interrupt"); -#ifdef __ISAPNP__ +#if defined(__ISAPNP__) && !defined(CONFIG_X86_PC9800) MODULE_PARM(nopnp, "i"); MODULE_PARM_DESC(nopnp, "disable ISA PnP support (0-1)"); MODULE_DEVICE_TABLE(isapnp, el3_isapnp_adapters); diff --git a/drivers/net/8390.h b/drivers/net/8390.h index 4debea1fd190..b9a61079dc5d 100644 --- a/drivers/net/8390.h +++ b/drivers/net/8390.h @@ -123,7 +123,8 @@ struct ei_device { #define inb_p(port) in_8(port) #define outb_p(val,port) out_8(port,val) -#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) +#elif defined(CONFIG_ARM_ETHERH) || defined(CONFIG_ARM_ETHERH_MODULE) || \ + defined(CONFIG_NET_CBUS) #define EI_SHIFT(x) (ei_local->reg_offset[x]) #else #define EI_SHIFT(x) (x) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d770d320577f..28b6f1c150c3 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -663,7 +663,7 @@ config EL16 as . config EL3 - tristate "3c509/3c529 (MCA)/3c579 \"EtherLink III\" support" + tristate "3c509/3c529 (MCA)/3c569B (98)/3c579 \"EtherLink III\" support" depends on NET_VENDOR_3COM && (ISA || EISA || MCA) ---help--- If you have a network (Ethernet) card belonging to the 3Com @@ -932,7 +932,7 @@ config NI65 source "drivers/net/tulip/Kconfig" config AT1700 - tristate "AT1700/1720 support (EXPERIMENTAL)" + tristate "AT1700/1720/RE1000Plus(C-Bus) support (EXPERIMENTAL)" depends on NET_ETHERNET && (ISA || MCA) && EXPERIMENTAL ---help--- If you have a network (Ethernet) card of this type, say Y and read @@ -978,7 +978,7 @@ config HP100 config NET_ISA bool "Other ISA cards" - depends on NET_ETHERNET && ISA + depends on NET_ETHERNET && ISA && !X86_PC9800 ---help--- If your network (Ethernet) card hasn't been mentioned yet and its bus system (that's the way the cards talks to the other components @@ -1176,6 +1176,55 @@ config SK_G16 the Ethernet-HOWTO, available from . +config NET_CBUS + bool "NEC PC-9800 C-bus cards" + depends on NET_ETHERNET && ISA && X86_PC9800 + ---help--- + If your network (Ethernet) card hasn't been mentioned yet and its + bus system (that's the way the cards talks to the other components + of your computer) is NEC PC-9800 C-Bus, say Y. + +config NE2K_CBUS + tristate "Most NE2000-based Ethernet support" + depends on NET_CBUS + +config NE2K_CBUS_EGY98 + bool "Melco EGY-98 support" + depends on NE2K_CBUS + +config NE2K_CBUS_LGY98 + bool "Melco LGY-98 support" + depends on NE2K_CBUS + +config NE2K_CBUS_ICM + bool "ICM IF-27xxET support" + depends on NE2K_CBUS + +config NE2K_CBUS_IOLA98 + bool "I-O DATA LA-98 support" + depends on NE2K_CBUS + +config NE2K_CBUS_CNET98EL + bool "Contec C-NET(98)E/L support" + depends on NE2K_CBUS + +config NE2K_CBUS_CNET98EL_IO_BASE + hex "C-NET(98)E/L I/O base address (0xaaed or 0x55ed)" + depends on NE2K_CBUS_CNET98EL + default "0xaaed" + +config NE2K_CBUS_ATLA98 + bool "Allied Telesis LA-98 Support" + depends on NE2K_CBUS + +config NE2K_CBUS_BDN + bool "ELECOM Laneed LD-BDN[123]A Support" + depends on NE2K_CBUS + +config NE2K_CBUS_NEC108 + bool "NEC PC-9801-108 Support" + depends on NE2K_CBUS + config SKMC tristate "SKnet MCA support" depends on NET_ETHERNET && MCA diff --git a/drivers/net/Makefile b/drivers/net/Makefile index b0b65d9cdbd8..9ad7798d4b1f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -81,6 +81,7 @@ obj-$(CONFIG_ARM_ETHERH) += 8390.o obj-$(CONFIG_WD80x3) += wd.o 8390.o obj-$(CONFIG_EL2) += 3c503.o 8390.o obj-$(CONFIG_NE2000) += ne.o 8390.o +obj-$(CONFIG_NE2K_CBUS) += ne2k_cbus.o 8390.o obj-$(CONFIG_NE2_MCA) += ne2.o 8390.o obj-$(CONFIG_HPLAN) += hp.o 8390.o obj-$(CONFIG_HPLAN_PLUS) += hp-plus.o 8390.o diff --git a/drivers/net/Makefile.lib b/drivers/net/Makefile.lib index c918d456d1b3..44e3b9b329e9 100644 --- a/drivers/net/Makefile.lib +++ b/drivers/net/Makefile.lib @@ -19,6 +19,7 @@ obj-$(CONFIG_MACE) += crc32.o obj-$(CONFIG_MACMACE) += crc32.o obj-$(CONFIG_MIPS_AU1000_ENET) += crc32.o obj-$(CONFIG_NATSEMI) += crc32.o +obj-$(CONFIG_NE2K_CBUS) += crc32.o obj-$(CONFIG_PCMCIA_FMVJ18X) += crc32.o obj-$(CONFIG_PCMCIA_SMC91C92) += crc32.o obj-$(CONFIG_PCMCIA_XIRTULIP) += crc32.o diff --git a/drivers/net/Space.c b/drivers/net/Space.c index 134b45257a5c..b09a14ceae14 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c @@ -233,7 +233,7 @@ static struct devprobe isa_probes[] __initdata = { #ifdef CONFIG_E2100 /* Cabletron E21xx series. */ {e2100_probe, 0}, #endif -#ifdef CONFIG_NE2000 /* ISA (use ne2k-pci for PCI cards) */ +#if defined(CONFIG_NE2000) || defined(CONFIG_NE2K_CBUS) /* ISA & PC-9800 CBUS (use ne2k-pci for PCI cards) */ {ne_probe, 0}, #endif #ifdef CONFIG_LANCE /* ISA/VLB (use pcnet32 for PCI cards) */ diff --git a/drivers/net/at1700.c b/drivers/net/at1700.c index 0c21dc3db762..d98c1e8f55bd 100644 --- a/drivers/net/at1700.c +++ b/drivers/net/at1700.c @@ -34,6 +34,10 @@ only is it difficult to detect, it also moves around in I/O space in response to inb()s from other device probes! */ +/* + 99/03/03 Allied Telesis RE1000 Plus support by T.Hagawa + 99/12/30 port to 2.3.35 by K.Takai +*/ #include #include @@ -76,10 +80,17 @@ static int fmv18x_probe_list[] __initdata = { * ISA */ +#ifndef CONFIG_X86_PC9800 static int at1700_probe_list[] __initdata = { 0x260, 0x280, 0x2a0, 0x240, 0x340, 0x320, 0x380, 0x300, 0 }; +#else /* CONFIG_X86_PC9800 */ +static int at1700_probe_list[] __initdata = { + 0x1d6, 0x1d8, 0x1da, 0x1d4, 0xd4, 0xd2, 0xd8, 0xd0, 0 +}; + +#endif /* CONFIG_X86_PC9800 */ /* * MCA */ @@ -122,6 +133,7 @@ struct net_local { /* Offsets from the base address. */ +#ifndef CONFIG_X86_PC9800 #define STATUS 0 #define TX_STATUS 0 #define RX_STATUS 1 @@ -136,6 +148,7 @@ struct net_local { #define TX_START 10 #define COL16CNTL 11 /* Controll Reg for 16 collisions */ #define MODE13 13 +#define RX_CTRL 14 /* Configuration registers only on the '865A/B chips. */ #define EEPROM_Ctrl 16 #define EEPROM_Data 17 @@ -144,8 +157,39 @@ struct net_local { #define IOCONFIG 18 /* Either read the jumper, or move the I/O. */ #define IOCONFIG1 19 #define SAPROM 20 /* The station address PROM, if no EEPROM. */ +#define MODE24 24 #define RESET 31 /* Write to reset some parts of the chip. */ #define AT1700_IO_EXTENT 32 +#define PORT_OFFSET(o) (o) +#else /* CONFIG_X86_PC9800 */ +#define STATUS (0x0000) +#define TX_STATUS (0x0000) +#define RX_STATUS (0x0001) +#define TX_INTR (0x0200)/* Bit-mapped interrupt enable registers. */ +#define RX_INTR (0x0201) +#define TX_MODE (0x0400) +#define RX_MODE (0x0401) +#define CONFIG_0 (0x0600)/* Misc. configuration settings. */ +#define CONFIG_1 (0x0601) +/* Run-time register bank 2 definitions. */ +#define DATAPORT (0x0800)/* Word-wide DMA or programmed-I/O dataport. */ +#define TX_START (0x0a00) +#define COL16CNTL (0x0a01)/* Controll Reg for 16 collisions */ +#define MODE13 (0x0c01) +#define RX_CTRL (0x0e00) +/* Configuration registers only on the '865A/B chips. */ +#define EEPROM_Ctrl (0x1000) +#define EEPROM_Data (0x1200) +#define CARDSTATUS 16 /* FMV-18x Card Status */ +#define CARDSTATUS1 17 /* FMV-18x Card Status */ +#define IOCONFIG (0x1400)/* Either read the jumper, or move the I/O. */ +#define IOCONFIG1 (0x1600) +#define SAPROM 20 /* The station address PROM, if no EEPROM. */ +#define MODE24 (0x1800)/* The station address PROM, if no EEPROM. */ +#define RESET (0x1e01)/* Write to reset some parts of the chip. */ +#define PORT_OFFSET(o) ({ int _o_ = (o); (_o_ & ~1) * 0x100 + (_o_ & 1); }) +#endif /* CONFIG_X86_PC9800 */ + #define TX_TIMEOUT 10 @@ -225,8 +269,20 @@ static int __init at1700_probe1(struct net_device *dev, int ioaddr) int slot, ret = -ENODEV; struct net_local *lp; +#ifndef CONFIG_X86_PC9800 if (!request_region(ioaddr, AT1700_IO_EXTENT, dev->name)) return -EBUSY; +#else + for (i = 0; i < 0x2000; i += 0x0200) { + if (!request_region(ioaddr + i, 2, dev->name)) { + while (i > 0) { + i -= 0x0200; + release_region(ioaddr + i, 2); + } + return -EBUSY; + } + } +#endif /* Resetting the chip doesn't reset the ISA interface, so don't bother. That means we have to be careful with the register values we probe for. @@ -317,10 +373,17 @@ found: /* Reset the internal state machines. */ outb(0, ioaddr + RESET); - if (is_at1700) + if (is_at1700) { +#ifndef CONFIG_X86_PC9800 irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04) | (read_eeprom(ioaddr, 0)>>14)]; - else { +#else + { + char re1000plus_irqmap[4] = {3, 5, 6, 12}; + irq = re1000plus_irqmap[inb(ioaddr + IOCONFIG1) >> 6]; + } +#endif + } else { /* Check PnP mode for FMV-183/184/183A/184A. */ /* This PnP routine is very poor. IO and IRQ should be known. */ if (inb(ioaddr + CARDSTATUS1) & 0x20) { @@ -392,18 +455,22 @@ found: /* Set the station address in bank zero. */ outb(0x00, ioaddr + CONFIG_1); for (i = 0; i < 6; i++) - outb(dev->dev_addr[i], ioaddr + 8 + i); + outb(dev->dev_addr[i], ioaddr + PORT_OFFSET(8 + i)); /* Switch to bank 1 and set the multicast table to accept none. */ outb(0x04, ioaddr + CONFIG_1); for (i = 0; i < 8; i++) - outb(0x00, ioaddr + 8 + i); + outb(0x00, ioaddr + PORT_OFFSET(8 + i)); /* Switch to bank 2 */ /* Lock our I/O address, and set manual processing mode for 16 collisions. */ outb(0x08, ioaddr + CONFIG_1); +#ifndef CONFIG_X86_PC9800 outb(dev->if_port, ioaddr + MODE13); +#else + outb(0, ioaddr + MODE13); +#endif outb(0x00, ioaddr + COL16CNTL); if (net_debug) @@ -447,7 +514,12 @@ err_out_priv: kfree(dev->priv); dev->priv = NULL; err_out: +#ifndef CONFIG_X86_PC9800 release_region(ioaddr, AT1700_IO_EXTENT); +#else + for (i = 0; i < 0x2000; i += 0x0200) + release_region(ioaddr + i, 2); +#endif return ret; } @@ -459,7 +531,11 @@ err_out: #define EE_DATA_READ 0x80 /* EEPROM chip data out, in reg. 17. */ /* Delay between EEPROM clock transitions. */ +#ifndef CONFIG_X86_PC9800 #define eeprom_delay() do { } while (0) +#else +#define eeprom_delay() __asm__ ("out%B0 %%al,%0" :: "N"(0x5f)) +#endif /* The EEPROM commands include the alway-set leading bit. */ #define EE_WRITE_CMD (5 << 6) @@ -542,12 +618,12 @@ static void net_tx_timeout (struct net_device *dev) inw (ioaddr + STATUS), inb (ioaddr + TX_STATUS) & 0x80 ? "IRQ conflict" : "network cable problem"); printk ("%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n", - dev->name, inw (ioaddr + 0), inw (ioaddr + 2), inw (ioaddr + 4), - inw (ioaddr + 6), inw (ioaddr + 8), inw (ioaddr + 10), - inw (ioaddr + 12), inw (ioaddr + 14)); + dev->name, inw(ioaddr + TX_STATUS), inw(ioaddr + TX_INTR), inw(ioaddr + TX_MODE), + inw(ioaddr + CONFIG_0), inw(ioaddr + DATAPORT), inw(ioaddr + TX_START), + inw(ioaddr + MODE13 - 1), inw(ioaddr + RX_CTRL)); lp->stats.tx_errors++; /* ToDo: We should try to restart the adaptor... */ - outw (0xffff, ioaddr + 24); + outw(0xffff, ioaddr + MODE24); outw (0xffff, ioaddr + TX_STATUS); outb (0x5a, ioaddr + CONFIG_0); outb (0xe8, ioaddr + CONFIG_1); @@ -704,7 +780,7 @@ net_rx(struct net_device *dev) dev->name, inb(ioaddr + RX_MODE), status); #ifndef final_version if (status == 0) { - outb(0x05, ioaddr + 14); + outb(0x05, ioaddr + RX_CTRL); break; } #endif @@ -724,7 +800,7 @@ net_rx(struct net_device *dev) dev->name, pkt_len); /* Prime the FIFO and then flush the packet. */ inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT); - outb(0x05, ioaddr + 14); + outb(0x05, ioaddr + RX_CTRL); lp->stats.rx_errors++; break; } @@ -734,7 +810,7 @@ net_rx(struct net_device *dev) dev->name, pkt_len); /* Prime the FIFO and then flush the packet. */ inw(ioaddr + DATAPORT); inw(ioaddr + DATAPORT); - outb(0x05, ioaddr + 14); + outb(0x05, ioaddr + RX_CTRL); lp->stats.rx_dropped++; break; } @@ -761,7 +837,7 @@ net_rx(struct net_device *dev) if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40) break; inw(ioaddr + DATAPORT); /* dummy status read */ - outb(0x05, ioaddr + 14); + outb(0x05, ioaddr + RX_CTRL); } if (net_debug > 5) @@ -844,24 +920,28 @@ set_rx_mode(struct net_device *dev) outb(0x02, ioaddr + RX_MODE); /* Use normal mode. */ } - save_flags(flags); - cli(); + spin_lock_irqsave (&lp->lock, flags); if (memcmp(mc_filter, lp->mc_filter, sizeof(mc_filter))) { int saved_bank = inw(ioaddr + CONFIG_0); /* Switch to bank 1 and set the multicast table. */ outw((saved_bank & ~0x0C00) | 0x0480, ioaddr + CONFIG_0); for (i = 0; i < 8; i++) - outb(mc_filter[i], ioaddr + 8 + i); + outb(mc_filter[i], ioaddr + PORT_OFFSET(8 + i)); memcpy(lp->mc_filter, mc_filter, sizeof(mc_filter)); outw(saved_bank, ioaddr + CONFIG_0); } - restore_flags(flags); + spin_unlock_irqrestore (&lp->lock, flags); return; } #ifdef MODULE static struct net_device dev_at1700; +#ifndef CONFIG_X86_PC9800 static int io = 0x260; +#else +static int io = 0xd0; +#endif + static int irq; MODULE_PARM(io, "i"); @@ -901,7 +981,15 @@ cleanup_module(void) /* If we don't do this, we can't re-insmod it later. */ free_irq(dev_at1700.irq, NULL); +#ifndef CONFIG_X86_PC9800 release_region(dev_at1700.base_addr, AT1700_IO_EXTENT); +#else + { + int i; + for (i = 0; i < 0x2000; i += 0x200) + release_region(dev_at1700.base_addr + i, 2); + } +#endif } #endif /* MODULE */ MODULE_LICENSE("GPL"); diff --git a/drivers/net/ne2k_cbus.c b/drivers/net/ne2k_cbus.c new file mode 100644 index 000000000000..861e1086934c --- /dev/null +++ b/drivers/net/ne2k_cbus.c @@ -0,0 +1,879 @@ +/* ne.c: A general non-shared-memory NS8390 ethernet driver for linux. */ +/* + Written 1992-94 by Donald Becker. + + Copyright 1993 United States Government as represented by the + Director, National Security Agency. + + This software may be used and distributed according to the terms + of the GNU General Public License, incorporated herein by reference. + + The author may be reached as becker@scyld.com, or C/O + Scyld Computing Corporation, 410 Severn Ave., Suite 210, Annapolis MD 21403 + + This driver should work with many programmed-I/O 8390-based ethernet + boards. Currently it supports the NE1000, NE2000, many clones, + and some Cabletron products. + + Changelog: + + Paul Gortmaker : use ENISR_RDC to monitor Tx PIO uploads, made + sanity checks and bad clone support optional. + Paul Gortmaker : new reset code, reset card after probe at boot. + Paul Gortmaker : multiple card support for module users. + Paul Gortmaker : Support for PCI ne2k clones, similar to lance.c + Paul Gortmaker : Allow users with bad cards to avoid full probe. + Paul Gortmaker : PCI probe changes, more PCI cards supported. + rjohnson@analogic.com : Changed init order so an interrupt will only + occur after memory is allocated for dev->priv. Deallocated memory + last in cleanup_modue() + Richard Guenther : Added support for ISAPnP cards + Paul Gortmaker : Discontinued PCI support - use ne2k-pci.c instead. + Osamu Tomita : Separate driver for NEC PC-9800. + +*/ + +/* Routines for the NatSemi-based designs (NE[12]000). */ + +static const char version1[] = +"ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)\n"; +static const char version2[] = +"Last modified Nov 1, 2000 by Paul Gortmaker\n"; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "8390.h" + +/* Some defines that people can play with if so inclined. */ + +/* Do we support clones that don't adhere to 14,15 of the SAprom ? */ +#define SUPPORT_NE_BAD_CLONES + +/* Do we perform extra sanity checks on stuff ? */ +/* #define NE_SANITY_CHECK */ + +/* Do we implement the read before write bugfix ? */ +/* #define NE_RW_BUGFIX */ + +/* Do we have a non std. amount of memory? (in units of 256 byte pages) */ +/* #define PACKETBUF_MEMSIZE 0x40 */ + +#ifdef SUPPORT_NE_BAD_CLONES +/* A list of bad clones that we none-the-less recognize. */ +static struct { const char *name8, *name16; unsigned char SAprefix[4];} +bad_clone_list[] __initdata = { + {"LA/T-98?", "LA/T-98", {0x00, 0xa0, 0xb0}}, /* I/O Data */ + {"EGY-98?", "EGY-98", {0x00, 0x40, 0x26}}, /* Melco EGY98 */ + {"ICM?", "ICM-27xx-ET", {0x00, 0x80, 0xc8}}, /* ICM IF-27xx-ET */ + {"CNET-98/EL?", "CNET(98)E/L", {0x00, 0x80, 0x4C}}, /* Contec CNET-98/EL */ + {0,} +}; +#endif + +/* ---- No user-serviceable parts below ---- */ + +#define NE_BASE (dev->base_addr) +#define NE_CMD EI_SHIFT(0x00) +#define NE_DATAPORT EI_SHIFT(0x10) /* NatSemi-defined port window offset. */ +#define NE_RESET EI_SHIFT(0x1f) /* Issue a read to reset, a write to clear. */ +#define NE_IO_EXTENT 0x20 + +#define NE1SM_START_PG 0x20 /* First page of TX buffer */ +#define NE1SM_STOP_PG 0x40 /* Last page +1 of RX ring */ +#define NESM_START_PG 0x40 /* First page of TX buffer */ +#define NESM_STOP_PG 0x80 /* Last page +1 of RX ring */ + +#include "ne2k_cbus.h" + +int ne_probe(struct net_device *dev); +static int ne_probe1(struct net_device *dev, int ioaddr); +static int ne_open(struct net_device *dev); +static int ne_close(struct net_device *dev); + +static void ne_reset_8390(struct net_device *dev); +static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, + int ring_page); +static void ne_block_input(struct net_device *dev, int count, + struct sk_buff *skb, int ring_offset); +static void ne_block_output(struct net_device *dev, const int count, + const unsigned char *buf, const int start_page); + + +/* Probe for various non-shared-memory ethercards. + + NEx000-clone boards have a Station Address PROM (SAPROM) in the packet + buffer memory space. NE2000 clones have 0x57,0x57 in bytes 0x0e,0x0f of + the SAPROM, while other supposed NE2000 clones must be detected by their + SA prefix. + + Reading the SAPROM from a word-wide card with the 8390 set in byte-wide + mode results in doubled values, which can be detected and compensated for. + + The probe is also responsible for initializing the card and filling + in the 'dev' and 'ei_status' structures. + + We use the minimum memory size for some ethercard product lines, iff we can't + distinguish models. You can increase the packet buffer size by setting + PACKETBUF_MEMSIZE. Reported Cabletron packet buffer locations are: + E1010 starts at 0x100 and ends at 0x2000. + E1010-x starts at 0x100 and ends at 0x8000. ("-x" means "more memory") + E2010 starts at 0x100 and ends at 0x4000. + E2010-x starts at 0x100 and ends at 0xffff. */ + +int __init ne_probe(struct net_device *dev) +{ + unsigned int base_addr = dev->base_addr; + + SET_MODULE_OWNER(dev); + + if (ei_debug > 2) + printk(KERN_DEBUG "ne_probe(): entered.\n"); + + /* If CONFIG_NET_CBUS, + we need dev->priv->reg_offset BEFORE to probe */ + if (ne2k_cbus_init(dev) != 0) + return -ENOMEM; + + /* First check any supplied i/o locations. User knows best. */ + if (base_addr > 0) { + int result; + const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); + + if (ei_debug > 2) + printk(KERN_DEBUG "ne_probe(): call ne_probe_cbus(base_addr=0x%x)\n", base_addr); + + result = ne_probe_cbus(dev, hw, base_addr); + if (result != 0) + ne2k_cbus_destroy(dev); + + return result; + } + + if (ei_debug > 2) + printk(KERN_DEBUG "ne_probe(): base_addr is not specified.\n"); + +#ifndef MODULE + /* Last resort. The semi-risky C-Bus auto-probe. */ + if (ei_debug > 2) + printk(KERN_DEBUG "ne_probe(): auto-probe start.\n"); + + { + const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); + + if (hw && hw->hwtype) { + const unsigned short *plist; + for (plist = hw->portlist; *plist; plist++) + if (ne_probe_cbus(dev, hw, *plist) == 0) + return 0; + } else { + for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) { + const unsigned short *plist; + for (plist = hw->portlist; *plist; plist++) + if (ne_probe_cbus(dev, hw, *plist) == 0) + return 0; + } + } + } +#endif + + ne2k_cbus_destroy(dev); + + return -ENODEV; +} + +static int __init ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr) +{ + if (ei_debug > 2) + printk(KERN_DEBUG "ne_probe_cbus(): entered. (called from %p)\n", + __builtin_return_address(0)); + + if (hw && hw->hwtype) { + ne2k_cbus_set_hwtype(dev, hw, ioaddr); + return ne_probe1(dev, ioaddr); + } else { + /* auto detect */ + + printk(KERN_DEBUG "ne_probe_cbus(): try to determine hardware types.\n"); + for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) { + ne2k_cbus_set_hwtype(dev, hw, ioaddr); + if (ne_probe1(dev, ioaddr) == 0) + return 0; + } + } + return -ENODEV; +} + +static int __init ne_probe1(struct net_device *dev, int ioaddr) +{ + int i; + unsigned char SA_prom[32]; + int wordlength = 2; + const char *name = NULL; + int start_page, stop_page; + int neX000, bad_card; + int reg0, ret; + static unsigned version_printed; + const struct ne2k_cbus_region *rlist; + const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); + struct ei_device *ei_local = (struct ei_device *)(dev->priv); + +#ifdef CONFIG_NE2K_CBUS_CNET98EL + if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) { + outb_p(0, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE); + /* udelay(5000); */ + outb_p(1, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE); + /* udelay(5000); */ + outb_p((ioaddr & 0xf000) >> 8 | 0x08 | 0x01, CONFIG_NE2K_CBUS_CNET98EL_IO_BASE + 2); + /* udelay(5000); */ + } +#endif + + for (rlist = hw->regionlist; rlist->range; rlist++) + if (!request_region(ioaddr + rlist->start, + rlist->range, dev->name)) { + ret = -EBUSY; + goto err_out; + } + + reg0 = inb_p(ioaddr + EI_SHIFT(0)); + if (reg0 == 0xFF) { + ret = -ENODEV; + goto err_out; + } + + /* Do a preliminary verification that we have a 8390. */ +#ifdef CONFIG_NE2K_CBUS_CNET98EL + if (hw->hwtype != NE2K_CBUS_HARDWARE_TYPE_CNET98EL) +#endif + { + int regd; + outb_p(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD); + regd = inb_p(ioaddr + EI_SHIFT(0x0d)); + outb_p(0xff, ioaddr + EI_SHIFT(0x0d)); + outb_p(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD); + inb_p(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */ + if (inb_p(ioaddr + EN0_COUNTER0) != 0) { + outb_p(reg0, ioaddr); + outb_p(regd, ioaddr + EI_SHIFT(0x0d)); /* Restore the old values. */ + ret = -ENODEV; + goto err_out; + } + } + + if (ei_debug && version_printed++ == 0) + printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2); + + printk(KERN_INFO "NE*000 ethercard probe at %#3x:", ioaddr); + + /* A user with a poor card that fails to ack the reset, or that + does not have a valid 0x57,0x57 signature can still use this + without having to recompile. Specifying an i/o address along + with an otherwise unused dev->mem_end value of "0xBAD" will + cause the driver to skip these parts of the probe. */ + + bad_card = ((dev->base_addr != 0) && (dev->mem_end == 0xbad)); + + /* Reset card. Who knows what dain-bramaged state it was left in. */ + + { + unsigned long reset_start_time = jiffies; + + /* derived from CNET98EL-patch for bad clones */ + outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD); + + /* DON'T change these to inb_p/outb_p or reset will fail on clones. */ + outb(inb(ioaddr + NE_RESET), ioaddr + NE_RESET); + + while ((inb_p(ioaddr + EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2*HZ/100) { + if (bad_card) { + printk(" (warning: no reset ack)"); + break; + } else { + printk(" not found (no reset ack).\n"); + ret = -ENODEV; + goto err_out; + } + } + + outb_p(0xff, ioaddr + EN0_ISR); /* Ack all intr. */ + } + +#ifdef CONFIG_NE2K_CBUS_CNET98EL + if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) { + static const char pat[32] ="AbcdeFghijKlmnoPqrstUvwxyZ789012"; + char buf[32]; + int maxwait = 200; + + if (ei_debug > 2) + printk(" [CNET98EL-specific initialize..."); + outb_p(E8390_NODMA | E8390_STOP, ioaddr + E8390_CMD); /* 0x20|0x1 */ + i = inb(ioaddr); + if ((i & ~0x2) != (0x20 | 0x01)) + return -ENODEV; + if ((inb(ioaddr + 0x7) & 0x80) != 0x80) + return -ENODEV; + outb_p(E8390_RXOFF, ioaddr + EN0_RXCR); /* out(ioaddr+0xc, 0x20) */ + /* outb_p(ENDCFG_WTS|ENDCFG_FT1|ENDCFG_LS, ioaddr+EN0_DCFG); */ + outb_p(ENDCFG_WTS | 0x48, ioaddr + EN0_DCFG); /* 0x49 */ + outb_p(CNET98EL_START_PG, ioaddr + EN0_STARTPG); + outb_p(CNET98EL_STOP_PG, ioaddr + EN0_STOPPG); + if (ei_debug > 2) + printk("memory check"); + for (i = 0; i < 65536; i += 1024) { + if (ei_debug > 2) + printk(" %04x", i); + ne2k_cbus_writemem(dev, ioaddr, i, pat, 32); + while (((inb(ioaddr + EN0_ISR) & ENISR_RDC) != ENISR_RDC) && --maxwait) + ; + ne2k_cbus_readmem(dev, ioaddr, i, buf, 32); + if (memcmp(pat, buf, 32)) { + if (ei_debug > 2) + printk(" failed."); + break; + } + } + if (i != 16384) { + if (ei_debug > 2) + printk("] "); + printk("memory failure at %x\n", i); + return -ENODEV; + } + if (ei_debug > 2) + printk(" good..."); + if (!dev->irq) { + if (ei_debug > 2) + printk("] "); + printk("IRQ must be specified for C-NET(98)E/L. probe failed.\n"); + return -ENODEV; + } + outb((dev->irq > 5) ? (dev->irq & 4):(dev->irq >> 1), ioaddr + (0x2 | 0x400)); + outb(0x7e, ioaddr + (0x4 | 0x400)); + ne2k_cbus_readmem(dev, ioaddr, 16384, SA_prom, 32); + outb(0xff, ioaddr + EN0_ISR); + if (ei_debug > 2) + printk("done]"); + } else +#endif /* CONFIG_NE2K_CBUS_CNET98EL */ + /* Read the 16 bytes of station address PROM. + We must first initialize registers, similar to NS8390_init(eifdev, 0). + We can't reliably read the SAPROM address without this. + (I learned the hard way!). */ + { + struct {unsigned char value; unsigned short offset;} program_seq[] = + { + {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ + /* NEC PC-9800: some board can only handle word-wide access? */ + {0x48 | ENDCFG_WTS, EN0_DCFG}, /* Set word-wide (0x48) access. */ + {16384 / 256, EN0_STARTPG}, + {32768 / 256, EN0_STOPPG}, + {0x00, EN0_RCNTLO}, /* Clear the count regs. */ + {0x00, EN0_RCNTHI}, + {0x00, EN0_IMR}, /* Mask completion irq. */ + {0xFF, EN0_ISR}, + {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ + {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ + {32, EN0_RCNTLO}, + {0x00, EN0_RCNTHI}, + {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ + {0x00, EN0_RSARHI}, + {E8390_RREAD+E8390_START, E8390_CMD}, + }; + + for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) + outb_p(program_seq[i].value, ioaddr + program_seq[i].offset); + insw(ioaddr + NE_DATAPORT, SA_prom, 32 >> 1); + + } + + if (wordlength == 2) + { + for (i = 0; i < 16; i++) + SA_prom[i] = SA_prom[i+i]; + start_page = NESM_START_PG; + stop_page = NESM_STOP_PG; +#ifdef CONFIG_NE2K_CBUS_CNET98EL + if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_CNET98EL) { + start_page = CNET98EL_START_PG; + stop_page = CNET98EL_STOP_PG; + } +#endif + } else { + start_page = NE1SM_START_PG; + stop_page = NE1SM_STOP_PG; + } + + neX000 = (SA_prom[14] == 0x57 && SA_prom[15] == 0x57); + if (neX000) { + name = "C-Bus-NE2K-compat"; + } + else + { +#ifdef SUPPORT_NE_BAD_CLONES + /* Ack! Well, there might be a *bad* NE*000 clone there. + Check for total bogus addresses. */ + for (i = 0; bad_clone_list[i].name8; i++) + { + if (SA_prom[0] == bad_clone_list[i].SAprefix[0] && + SA_prom[1] == bad_clone_list[i].SAprefix[1] && + SA_prom[2] == bad_clone_list[i].SAprefix[2]) + { + if (wordlength == 2) + { + name = bad_clone_list[i].name16; + } else { + name = bad_clone_list[i].name8; + } + break; + } + } + if (bad_clone_list[i].name8 == NULL) + { + printk(" not found (invalid signature %2.2x %2.2x).\n", + SA_prom[14], SA_prom[15]); + ret = -ENXIO; + goto err_out; + } +#else + printk(" not found.\n"); + ret = -ENXIO; + goto err_out; +#endif + } + + if (dev->irq < 2) + { + unsigned long cookie = probe_irq_on(); + outb_p(0x50, ioaddr + EN0_IMR); /* Enable one interrupt. */ + outb_p(0x00, ioaddr + EN0_RCNTLO); + outb_p(0x00, ioaddr + EN0_RCNTHI); + outb_p(E8390_RREAD+E8390_START, ioaddr); /* Trigger it... */ + mdelay(10); /* wait 10ms for interrupt to propagate */ + outb_p(0x00, ioaddr + EN0_IMR); /* Mask it again. */ + dev->irq = probe_irq_off(cookie); + if (ei_debug > 2) + printk(" autoirq is %d\n", dev->irq); + } else if (dev->irq == 7) + /* Fixup for users that don't know that IRQ 7 is really IRQ 11, + or don't know which one to set. */ + dev->irq = 11; + + if (! dev->irq) { + printk(" failed to detect IRQ line.\n"); + ret = -EAGAIN; + goto err_out; + } + + /* Allocate dev->priv and fill in 8390 specific dev fields. */ + if (ethdev_init(dev)) + { + printk (" unable to get memory for dev->priv.\n"); + ret = -ENOMEM; + goto err_out; + } + + /* Snarf the interrupt now. There's no point in waiting since we cannot + share and the board will usually be enabled. */ + ret = request_irq(dev->irq, ei_interrupt, 0, name, dev); + if (ret) { + printk (" unable to get IRQ %d (errno=%d).\n", dev->irq, ret); + goto err_out_kfree; + } + + dev->base_addr = ioaddr; + + for(i = 0; i < ETHER_ADDR_LEN; i++) { + printk(" %2.2x", SA_prom[i]); + dev->dev_addr[i] = SA_prom[i]; + } + + printk("\n%s: %s found at %#x, hardware type %d(%s), using IRQ %d.\n", + dev->name, name, ioaddr, hw->hwtype, hw->hwident, dev->irq); + + ei_status.name = name; + ei_status.tx_start_page = start_page; + ei_status.stop_page = stop_page; + ei_status.word16 = (wordlength == 2); + + ei_status.rx_start_page = start_page + TX_PAGES; +#ifdef PACKETBUF_MEMSIZE + /* Allow the packet buffer size to be overridden by know-it-alls. */ + ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE; +#endif + + ei_status.reset_8390 = &ne_reset_8390; + ei_status.block_input = &ne_block_input; + ei_status.block_output = &ne_block_output; + ei_status.get_8390_hdr = &ne_get_8390_hdr; + ei_status.priv = 0; + dev->open = &ne_open; + dev->stop = &ne_close; + NS8390_init(dev, 0); + return 0; + +err_out_kfree: + ne2k_cbus_destroy(dev); +err_out: + while (rlist > hw->regionlist) { + rlist --; + release_region(ioaddr + rlist->start, rlist->range); + } + return ret; +} + +static int ne_open(struct net_device *dev) +{ + ei_open(dev); + return 0; +} + +static int ne_close(struct net_device *dev) +{ + if (ei_debug > 1) + printk(KERN_DEBUG "%s: Shutting down ethercard.\n", dev->name); + ei_close(dev); + return 0; +} + +/* Hard reset the card. This used to pause for the same period that a + 8390 reset command required, but that shouldn't be necessary. */ + +static void ne_reset_8390(struct net_device *dev) +{ + unsigned long reset_start_time = jiffies; + struct ei_device *ei_local = (struct ei_device *)(dev->priv); + + if (ei_debug > 1) + printk(KERN_DEBUG "resetting the 8390 t=%ld...", jiffies); + + /* derived from CNET98EL-patch for bad clones... */ + outb_p(E8390_NODMA | E8390_STOP, NE_BASE + E8390_CMD); /* 0x20 | 0x1 */ + + /* DON'T change these to inb_p/outb_p or reset will fail on clones. */ + outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); + + ei_status.txing = 0; + ei_status.dmaing = 0; + + /* This check _should_not_ be necessary, omit eventually. */ + while ((inb_p(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) + if (jiffies - reset_start_time > 2*HZ/100) { + printk(KERN_WARNING "%s: ne_reset_8390() did not complete.\n", dev->name); + break; + } + outb_p(ENISR_RESET, NE_BASE + EN0_ISR); /* Ack intr. */ +} + +/* Grab the 8390 specific header. Similar to the block_input routine, but + we don't need to be concerned with ring wrap as the header will be at + the start of a page, so we optimize accordingly. */ + +static void ne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page) +{ + int nic_base = dev->base_addr; + struct ei_device *ei_local = (struct ei_device *)(dev->priv); + + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ + + if (ei_status.dmaing) + { + printk(KERN_EMERG "%s: DMAing conflict in ne_get_8390_hdr " + "[DMAstat:%d][irqlock:%d].\n", + dev->name, ei_status.dmaing, ei_status.irqlock); + return; + } + + ei_status.dmaing |= 0x01; + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); + outb_p(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO); + outb_p(0, nic_base + EN0_RCNTHI); + outb_p(0, nic_base + EN0_RSARLO); /* On page boundary */ + outb_p(ring_page, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); + + if (ei_status.word16) + insw(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1); + else + insb(NE_BASE + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)); + + outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ + ei_status.dmaing &= ~0x01; + + le16_to_cpus(&hdr->count); +} + +/* Block input and output, similar to the Crynwr packet driver. If you + are porting to a new ethercard, look at the packet driver source for hints. + The NEx000 doesn't share the on-board packet memory -- you have to put + the packet out through the "remote DMA" dataport using outb. */ + +static void ne_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset) +{ +#ifdef NE_SANITY_CHECK + int xfer_count = count; +#endif + int nic_base = dev->base_addr; + char *buf = skb->data; + struct ei_device *ei_local = (struct ei_device *)(dev->priv); + + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ + if (ei_status.dmaing) + { + printk(KERN_EMERG "%s: DMAing conflict in ne_block_input " + "[DMAstat:%d][irqlock:%d].\n", + dev->name, ei_status.dmaing, ei_status.irqlock); + return; + } + ei_status.dmaing |= 0x01; + + /* round up count to a word (derived from ICM-patch) */ + count = (count + 1) & ~1; + + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD); + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(ring_offset & 0xff, nic_base + EN0_RSARLO); + outb_p(ring_offset >> 8, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); + if (ei_status.word16) + { + insw(NE_BASE + NE_DATAPORT,buf,count>>1); + if (count & 0x01) + { + buf[count-1] = inb(NE_BASE + NE_DATAPORT); +#ifdef NE_SANITY_CHECK + xfer_count++; +#endif + } + } else { + insb(NE_BASE + NE_DATAPORT, buf, count); + } + +#ifdef NE_SANITY_CHECK + /* This was for the ALPHA version only, but enough people have + been encountering problems so it is still here. If you see + this message you either 1) have a slightly incompatible clone + or 2) have noise/speed problems with your bus. */ + + if (ei_debug > 1) + { + /* DMA termination address check... */ + int addr, tries = 20; + do { + /* DON'T check for 'inb_p(EN0_ISR) & ENISR_RDC' here + -- it's broken for Rx on some cards! */ + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + addr = (high << 8) + low; + if (((ring_offset + xfer_count) & 0xff) == low) + break; + } while (--tries > 0); + if (tries <= 0) + printk(KERN_WARNING "%s: RX transfer address mismatch," + "%#4.4x (expected) vs. %#4.4x (actual).\n", + dev->name, ring_offset + xfer_count, addr); + } +#endif + outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ + ei_status.dmaing &= ~0x01; +} + +static void ne_block_output(struct net_device *dev, int count, + const unsigned char *buf, const int start_page) +{ + int nic_base = NE_BASE; + unsigned long dma_start; +#ifdef NE_SANITY_CHECK + int retries = 0; +#endif + struct ei_device *ei_local = (struct ei_device *)(dev->priv); + + /* Round the count up for word writes. Do we need to do this? + What effect will an odd byte count have on the 8390? + I should check someday. */ + + if (ei_status.word16 && (count & 0x01)) + count++; + + /* This *shouldn't* happen. If it does, it's the last thing you'll see */ + if (ei_status.dmaing) + { + printk(KERN_EMERG "%s: DMAing conflict in ne_block_output." + "[DMAstat:%d][irqlock:%d]\n", + dev->name, ei_status.dmaing, ei_status.irqlock); + return; + } + ei_status.dmaing |= 0x01; + /* We should already be in page 0, but to be safe... */ + outb_p(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD); + +#ifdef NE_SANITY_CHECK +retry: +#endif + +#ifdef NE8390_RW_BUGFIX + /* Handle the read-before-write bug the same way as the + Crynwr packet driver -- the NatSemi method doesn't work. + Actually this doesn't always work either, but if you have + problems with your NEx000 this is better than nothing! */ + + outb_p(0x42, nic_base + EN0_RCNTLO); + outb_p(0x00, nic_base + EN0_RCNTHI); + outb_p(0x42, nic_base + EN0_RSARLO); + outb_p(0x00, nic_base + EN0_RSARHI); + outb_p(E8390_RREAD+E8390_START, nic_base + NE_CMD); + /* Make certain that the dummy read has occurred. */ + udelay(6); +#endif + + outb_p(ENISR_RDC, nic_base + EN0_ISR); + + /* Now the normal output. */ + outb_p(count & 0xff, nic_base + EN0_RCNTLO); + outb_p(count >> 8, nic_base + EN0_RCNTHI); + outb_p(0x00, nic_base + EN0_RSARLO); + outb_p(start_page, nic_base + EN0_RSARHI); + + outb_p(E8390_RWRITE+E8390_START, nic_base + NE_CMD); + if (ei_status.word16) { + outsw(NE_BASE + NE_DATAPORT, buf, count>>1); + } else { + outsb(NE_BASE + NE_DATAPORT, buf, count); + } + + dma_start = jiffies; + +#ifdef NE_SANITY_CHECK + /* This was for the ALPHA version only, but enough people have + been encountering problems so it is still here. */ + + if (ei_debug > 1) + { + /* DMA termination address check... */ + int addr, tries = 20; + do { + int high = inb_p(nic_base + EN0_RSARHI); + int low = inb_p(nic_base + EN0_RSARLO); + addr = (high << 8) + low; + if ((start_page << 8) + count == addr) + break; + } while (--tries > 0); + + if (tries <= 0) + { + printk(KERN_WARNING "%s: Tx packet transfer address mismatch," + "%#4.4x (expected) vs. %#4.4x (actual).\n", + dev->name, (start_page << 8) + count, addr); + if (retries++ == 0) + goto retry; + } + } +#endif + + while ((inb_p(nic_base + EN0_ISR) & ENISR_RDC) == 0) + if (jiffies - dma_start > 2*HZ/100) { /* 20ms */ + printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); + ne_reset_8390(dev); + NS8390_init(dev,1); + break; + } + + outb_p(ENISR_RDC, nic_base + EN0_ISR); /* Ack intr. */ + ei_status.dmaing &= ~0x01; + return; +} + + +#ifdef MODULE +#define MAX_NE_CARDS 4 /* Max number of NE cards per module */ +static struct net_device dev_ne[MAX_NE_CARDS]; +static int io[MAX_NE_CARDS]; +static int irq[MAX_NE_CARDS]; +static int bad[MAX_NE_CARDS]; /* 0xbad = bad sig or no reset ack */ +static int hwtype[MAX_NE_CARDS] = { 0, }; /* board type */ + +MODULE_PARM(io, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); +MODULE_PARM(irq, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); +MODULE_PARM(bad, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); +MODULE_PARM(hwtype, "1-" __MODULE_STRING(MAX_NE_CARDS) "i"); +MODULE_PARM_DESC(io, "I/O base address(es),required"); +MODULE_PARM_DESC(irq, "IRQ number(s)"); +MODULE_PARM_DESC(bad, "Accept card(s) with bad signatures"); +MODULE_PARM_DESC(hwtype, "Board type of PC-9800 C-Bus NIC"); +MODULE_DESCRIPTION("NE1000/NE2000 PC-9800 C-bus Ethernet driver"); +MODULE_LICENSE("GPL"); + +/* This is set up so that no ISA autoprobe takes place. We can't guarantee +that the ne2k probe is the last 8390 based probe to take place (as it +is at boot) and so the probe will get confused by any other 8390 cards. +ISA device autoprobes on a running machine are not recommended anyway. */ + +int init_module(void) +{ + int this_dev, found = 0; + + for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { + struct net_device *dev = &dev_ne[this_dev]; + dev->irq = irq[this_dev]; + dev->mem_end = bad[this_dev]; + dev->base_addr = io[this_dev]; + dev->mem_start = hwtype[this_dev]; + dev->init = ne_probe; + if (register_netdev(dev) == 0) { + found++; + continue; + } + if (found != 0) { /* Got at least one. */ + return 0; + } + if (io[this_dev] != 0) + printk(KERN_WARNING "ne.c: No NE*000 card found at i/o = %#x\n", io[this_dev]); + else + printk(KERN_NOTICE "ne.c: You must supply \"io=0xNNN\" value(s) for C-Bus cards.\n"); + return -ENXIO; + } + return 0; +} + +void cleanup_module(void) +{ + int this_dev; + + for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) { + struct net_device *dev = &dev_ne[this_dev]; + if (dev->priv != NULL) { + const struct ne2k_cbus_region *rlist; + const struct ne2k_cbus_hwinfo *hw = ne2k_cbus_get_hwinfo((int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); + + free_irq(dev->irq, dev); + for (rlist = hw->regionlist; rlist->range; rlist++) { + release_region(dev->base_addr + rlist->start, + rlist->range); + } + unregister_netdev(dev); + ne2k_cbus_destroy(dev); + } + } +} +#endif /* MODULE */ + + +/* + * Local variables: + * compile-command: "gcc -DKERNEL -Wall -O6 -fomit-frame-pointer -I/usr/src/linux/net/tcp -c ne.c" + * version-control: t + * kept-new-versions: 5 + * End: + */ diff --git a/drivers/net/ne2k_cbus.h b/drivers/net/ne2k_cbus.h new file mode 100644 index 000000000000..e561ef7f6111 --- /dev/null +++ b/drivers/net/ne2k_cbus.h @@ -0,0 +1,481 @@ +/* ne2k_cbus.h: + vender-specific information definition for NEC PC-9800 + C-bus Ethernet Cards + Used in ne.c + + (C)1998,1999 KITAGWA Takurou & Linux/98 project +*/ + +#include + +#undef NE_RESET +#define NE_RESET EI_SHIFT(0x11) /* Issue a read to reset, a write to clear. */ + +#ifdef CONFIG_NE2K_CBUS_CNET98EL +#ifndef CONFIG_NE2K_CBUS_CNET98EL_IO_BASE +#warning CONFIG_NE2K_CBUS_CNET98EL_IO_BASE is not defined(config error?) +#warning use 0xaaed as default +#define CONFIG_NE2K_CBUS_CNET98EL_IO_BASE 0xaaed /* or 0x55ed */ +#endif +#define CNET98EL_START_PG 0x00 +#define CNET98EL_STOP_PG 0x40 +#endif + +/* Hardware type definition (derived from *BSD) */ +#define NE2K_CBUS_HARDWARE_TYPE_MASK 0xff + +/* 0: reserved for auto-detect */ +/* 1: (not tested) + Allied Telesis CentreCom LA-98-T */ +#define NE2K_CBUS_HARDWARE_TYPE_ATLA98 1 +/* 2: (not tested) + ELECOM Laneed + LD-BDN[123]A + PLANET SMART COM 98 EN-2298-C + MACNICA ME98 */ +#define NE2K_CBUS_HARDWARE_TYPE_BDN 2 +/* 3: + Melco EGY-98 + Contec C-NET(98)E*A/L*A,C-NET(98)P */ +#define NE2K_CBUS_HARDWARE_TYPE_EGY98 3 +/* 4: + Melco LGY-98,IND-SP,IND-SS + MACNICA NE2098 */ +#define NE2K_CBUS_HARDWARE_TYPE_LGY98 4 +/* 5: + ICM DT-ET-25,DT-ET-T5,IF-2766ET,IF-2771ET + PLANET SMART COM 98 EN-2298-T,EN-2298P-T + D-Link DE-298PT,DE-298PCAT + ELECOM Laneed LD-98P */ +#define NE2K_CBUS_HARDWARE_TYPE_ICM 5 +/* 6: (reserved for SIC-98, which is not supported in this driver.) */ +/* 7: (unused in *BSD?) + + +*/ +#define NE2K_CBUS_HARDWARE_TYPE_NE2K 7 +/* 8: + NEC PC-9801-108 */ +#define NE2K_CBUS_HARDWARE_TYPE_NEC108 8 +/* 9: + I-O DATA LA-98,LA/T-98 */ +#define NE2K_CBUS_HARDWARE_TYPE_IOLA98 9 +/* 10: (reserved for C-NET(98), which is not supported in this driver.) */ +/* 11: + Contec C-NET(98)E,L */ +#define NE2K_CBUS_HARDWARE_TYPE_CNET98EL 11 + +#define NE2K_CBUS_HARDWARE_TYPE_MAX 11 + +/* HARDWARE TYPE ID 12-31: reserved */ + +struct ne2k_cbus_offsetinfo { + unsigned short skip; + unsigned short offset8; /* +0x8 - +0xf */ + unsigned short offset10; /* +0x10 */ + unsigned short offset1f; /* +0x1f */ +}; + +struct ne2k_cbus_region { + unsigned short start; + short range; +}; + +struct ne2k_cbus_hwinfo { + const unsigned short hwtype; + const unsigned char *hwident; +#ifndef MODULE + const unsigned short *portlist; +#endif + const struct ne2k_cbus_offsetinfo *offsetinfo; + const struct ne2k_cbus_region *regionlist; +}; + +#ifdef CONFIG_NE2K_CBUS_ATLA98 +#ifndef MODULE +static unsigned short atla98_portlist[] __initdata = { + 0xd0, + 0 +}; +#endif +#define atla98_offsetinfo ne2k_offsetinfo +#define atla98_regionlist ne2k_regionlist +#endif /* CONFIG_NE2K_CBUS_ATLA98 */ + +#ifdef CONFIG_NE2K_CBUS_BDN +#ifndef MODULE +static unsigned short bdn_portlist[] __initdata = { + 0xd0, + 0 +}; +#endif +static struct ne2k_cbus_offsetinfo bdn_offsetinfo __initdata = { +#if 0 + /* comes from FreeBSD(98) ed98.h */ + 0x1000, 0x8000, 0x100, 0xc200 /* ??? */ +#else + /* comes from NetBSD/pc98 if_ne_isa.c */ + 0x1000, 0x8000, 0x100, 0x7f00 /* ??? */ +#endif +}; +static struct ne2k_cbus_region bdn_regionlist[] __initdata = { + {0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000,1}, + {0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1}, + {0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1}, + {0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1}, + {0x100, 1}, {0x7f00, 1}, + {0x0, 0} +}; +#endif /* CONFIG_NE2K_CBUS_BDN */ + +#ifdef CONFIG_NE2K_CBUS_EGY98 +#ifndef MODULE +static unsigned short egy98_portlist[] __initdata = { + 0xd0, + 0 +}; +#endif +static struct ne2k_cbus_offsetinfo egy98_offsetinfo __initdata = { + 0x02, 0x100, 0x200, 0x300 +}; +static struct ne2k_cbus_region egy98_regionlist[] __initdata = { + {0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1}, + {0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1}, + {0x100, 1}, {0x102, 1}, {0x104, 1}, {0x106, 1}, + {0x108, 1}, {0x10a, 1}, {0x10c, 1}, {0x10e, 1}, + {0x200, 1}, {0x300, 1}, + {0x0, 0} +}; +#endif /* CONFIG_NE2K_CBUS_EGY98 */ + +#ifdef CONFIG_NE2K_CBUS_LGY98 +#ifndef MODULE +static unsigned short lgy98_portlist[] __initdata = { + 0xd0, 0x10d0, 0x20d0, 0x30d0, 0x40d0, 0x50d0, 0x60d0, 0x70d0, + 0 +}; +#endif +static struct ne2k_cbus_offsetinfo lgy98_offsetinfo __initdata = { + 0x01, 0x08, 0x200, 0x300 +}; +static struct ne2k_cbus_region lgy98_regionlist[] __initdata = { + {0x0, 16}, {0x200, 1}, {0x300, 1}, + {0x0, 0} +}; +#endif /* CONFIG_NE2K_CBUS_LGY98 */ + +#ifdef CONFIG_NE2K_CBUS_ICM +#ifndef MODULE +static unsigned short icm_portlist[] __initdata = { + /* ICM */ + 0x56d0, + /* LD-98PT */ + 0x46d0, 0x66d0, 0x76d0, 0x86d0, 0x96d0, 0xa6d0, 0xb6d0, 0xc6d0, + 0 +}; +#endif +static struct ne2k_cbus_offsetinfo icm_offsetinfo __initdata = { + 0x01, 0x08, 0x100, 0x10f +}; +static struct ne2k_cbus_region icm_regionlist[] __initdata = { + {0x0, 16}, {0x100, 16}, + {0x0, 0} +}; +#endif /* CONFIG_NE2K_CBUS_ICM */ + +#if defined(CONFIG_NE2K_CBUS_NE2K) && !defined(MODULE) +static unsigned short ne2k_portlist[] __initdata = { + 0xd0, 0x300, 0x280, 0x320, 0x340, 0x360, 0x380, + 0 +}; +#endif +#if defined(CONFIG_NE2K_CBUS_NE2K) || defined(CONFIG_NE2K_CBUS_ATLA98) +static struct ne2k_cbus_offsetinfo ne2k_offsetinfo __initdata = { + 0x01, 0x08, 0x10, 0x1f +}; +static struct ne2k_cbus_region ne2k_regionlist[] __initdata = { + {0x0, 32}, + {0x0, 0} +}; +#endif + +#ifdef CONFIG_NE2K_CBUS_NEC108 +#ifndef MODULE +static unsigned short nec108_portlist[] __initdata = { + 0x770, 0x2770, 0x4770, 0x6770, + 0 +}; +#endif +static struct ne2k_cbus_offsetinfo nec108_offsetinfo __initdata = { + 0x02, 0x1000, 0x888, 0x88a +}; +static struct ne2k_cbus_region nec108_regionlist[] __initdata = { + {0x0, 1}, {0x2, 1}, {0x4, 1}, {0x6, 1}, + {0x8, 1}, {0xa, 1}, {0xc, 1}, {0xe, 1}, + {0x1000, 1}, {0x1002, 1}, {0x1004, 1}, {0x1006, 1}, + {0x1008, 1}, {0x100a, 1}, {0x100c, 1}, {0x100e, 1}, + {0x888, 1}, {0x88a, 1}, {0x88c, 1}, {0x88e, 1}, + {0x0, 0} +}; +#endif + +#ifdef CONFIG_NE2K_CBUS_IOLA98 +#ifndef MODULE +static unsigned short iola98_portlist[] __initdata = { + 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, + 0 +}; +#endif +static struct ne2k_cbus_offsetinfo iola98_offsetinfo __initdata = { + 0x1000, 0x8000, 0x100, 0xf100 +}; +static struct ne2k_cbus_region iola98_regionlist[] __initdata = { + {0x0, 1}, {0x1000, 1}, {0x2000, 1}, {0x3000, 1}, + {0x4000, 1}, {0x5000, 1}, {0x6000, 1}, {0x7000, 1}, + {0x8000, 1}, {0x9000, 1}, {0xa000, 1}, {0xb000, 1}, + {0xc000, 1}, {0xd000, 1}, {0xe000, 1}, {0xf000, 1}, + {0x100, 1}, {0xf100, 1}, + {0x0,0} +}; +#endif /* CONFIG_NE2K_CBUS_IOLA98 */ + +#ifdef CONFIG_NE2K_CBUS_CNET98EL +#ifndef MODULE +static unsigned short cnet98el_portlist[] __initdata = { + 0x3d0, 0x13d0, 0x23d0, 0x33d0, 0x43d0, 0x53d0, 0x60d0, 0x70d0, + 0 +}; +#endif +static struct ne2k_cbus_offsetinfo cnet98el_offsetinfo __initdata = { + 0x01, 0x08, 0x40e, 0x400 +}; +static struct ne2k_cbus_region cnet98el_regionlist[] __initdata = { + {0x0, 16}, {0x400, 16}, + {0x0, 0} +}; +#endif + + +/* port information table (for ne.c initialize/probe process) */ + +static struct ne2k_cbus_hwinfo ne2k_cbus_hwinfo_list[] __initdata = { +#ifdef CONFIG_NE2K_CBUS_ATLA98 +/* NOT TESTED */ + { + NE2K_CBUS_HARDWARE_TYPE_ATLA98, + "LA-98-T", +#ifndef MODULE + atla98_portlist, +#endif + &atla98_offsetinfo, atla98_regionlist + }, +#endif +#ifdef CONFIG_NE2K_CBUS_BDN +/* NOT TESTED */ + { + NE2K_CBUS_HARDWARE_TYPE_BDN, + "LD-BDN[123]A", +#ifndef MODULE + bdn_portlist, +#endif + &bdn_offsetinfo, bdn_regionlist + }, +#endif +#ifdef CONFIG_NE2K_CBUS_ICM + { + NE2K_CBUS_HARDWARE_TYPE_ICM, + "IF-27xxET", +#ifndef MODULE + icm_portlist, +#endif + &icm_offsetinfo, icm_regionlist + }, +#endif +#ifdef CONFIG_NE2K_CBUS_NE2K + { + NE2K_CBUS_HARDWARE_TYPE_NE2K, + "NE2000 compat.", +#ifndef MODULE + ne2k_portlist, +#endif + &ne2k_offsetinfo, ne2k_regionlist + }, +#endif +#ifdef CONFIG_NE2K_CBUS_NEC108 + { + NE2K_CBUS_HARDWARE_TYPE_NEC108, + "PC-9801-108", +#ifndef MODULE + nec108_portlist, +#endif + &nec108_offsetinfo, nec108_regionlist + }, +#endif +#ifdef CONFIG_NE2K_CBUS_IOLA98 + { + NE2K_CBUS_HARDWARE_TYPE_IOLA98, + "LA-98", +#ifndef MODULE + iola98_portlist, +#endif + &iola98_offsetinfo, iola98_regionlist + }, +#endif +#ifdef CONFIG_NE2K_CBUS_CNET98EL + { + NE2K_CBUS_HARDWARE_TYPE_CNET98EL, + "C-NET(98)E/L", +#ifndef MODULE + cnet98el_portlist, +#endif + &cnet98el_offsetinfo, cnet98el_regionlist + }, +#endif +/* NOTE: LGY98 must be probed before EGY98, or system stalled!? */ +#ifdef CONFIG_NE2K_CBUS_LGY98 + { + NE2K_CBUS_HARDWARE_TYPE_LGY98, + "LGY-98", +#ifndef MODULE + lgy98_portlist, +#endif + &lgy98_offsetinfo, lgy98_regionlist + }, +#endif +#ifdef CONFIG_NE2K_CBUS_EGY98 + { + NE2K_CBUS_HARDWARE_TYPE_EGY98, + "EGY-98", +#ifndef MODULE + egy98_portlist, +#endif + &egy98_offsetinfo, egy98_regionlist + }, +#endif + { + 0, + "unsupported hardware", +#ifndef MODULE + NULL, +#endif + NULL, NULL + } +}; + +static int __init ne2k_cbus_init(struct net_device *dev) +{ + struct ei_device *ei_local; + if (dev->priv == NULL) { + ei_local = kmalloc(sizeof(struct ei_device), GFP_KERNEL); + if (ei_local == NULL) + return -ENOMEM; + memset(ei_local, 0, sizeof(struct ei_device)); + ei_local->reg_offset = kmalloc(sizeof(typeof(*ei_local->reg_offset))*18, GFP_KERNEL); + if (ei_local->reg_offset == NULL) { + kfree(ei_local); + return -ENOMEM; + } + spin_lock_init(&ei_local->page_lock); + dev->priv = ei_local; + } + return 0; +} + +static void ne2k_cbus_destroy(struct net_device *dev) +{ + struct ei_device *ei_local = (struct ei_device *)(dev->priv); + if (ei_local != NULL) { + if (ei_local->reg_offset) + kfree(ei_local->reg_offset); + kfree(dev->priv); + dev->priv = NULL; + } +} + +static const struct ne2k_cbus_hwinfo * __init ne2k_cbus_get_hwinfo(int hwtype) +{ + const struct ne2k_cbus_hwinfo *hw; + + for (hw = &ne2k_cbus_hwinfo_list[0]; hw->hwtype; hw++) { + if (hw->hwtype == hwtype) break; + } + return hw; +} + +static void __init ne2k_cbus_set_hwtype(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr) +{ + struct ei_device *ei_local = (struct ei_device *)(dev->priv); + int i; + int hwtype_old = dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK; + + if (!ei_local) + panic("Gieee! ei_local == NULL!! (from %p)", + __builtin_return_address(0)); + + dev->mem_start &= ~NE2K_CBUS_HARDWARE_TYPE_MASK; + dev->mem_start |= hw->hwtype & NE2K_CBUS_HARDWARE_TYPE_MASK; + + if (ei_debug > 2) { + printk(KERN_DEBUG "hwtype changed: %d -> %d\n",hwtype_old,(int)(dev->mem_start & NE2K_CBUS_HARDWARE_TYPE_MASK)); + } + + if (hw->offsetinfo) { + for (i = 0; i < 8; i++) { + ei_local->reg_offset[i] = hw->offsetinfo->skip * i; + } + for (i = 8; i < 16; i++) { + ei_local->reg_offset[i] = + hw->offsetinfo->skip*(i-8) + hw->offsetinfo->offset8; + } +#ifdef CONFIG_NE2K_CBUS_NEC108 + if (hw->hwtype == NE2K_CBUS_HARDWARE_TYPE_NEC108) { + int adj = (ioaddr & 0xf000) /2; + ei_local->reg_offset[16] = + (hw->offsetinfo->offset10 | adj) - ioaddr; + ei_local->reg_offset[17] = + (hw->offsetinfo->offset1f | adj) - ioaddr; + } else { +#endif /* CONFIG_NE2K_CBUS_NEC108 */ + ei_local->reg_offset[16] = hw->offsetinfo->offset10; + ei_local->reg_offset[17] = hw->offsetinfo->offset1f; +#ifdef CONFIG_NE2K_CBUS_NEC108 + } +#endif + } else { + /* make dummmy offset list */ + for (i = 0; i < 16; i++) { + ei_local->reg_offset[i] = i; + } + ei_local->reg_offset[16] = 0x10; + ei_local->reg_offset[17] = 0x1f; + } +} + +#if defined(CONFIG_NE2K_CBUS_ICM) || defined(CONFIG_NE2K_CBUS_CNET98EL) +static void __init ne2k_cbus_readmem(struct net_device *dev, int ioaddr, unsigned short memaddr, char *buf, unsigned short len) +{ + struct ei_device *ei_local = (struct ei_device *)(dev->priv); + outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD); + outb_p(len & 0xff, ioaddr+EN0_RCNTLO); + outb_p(len >> 8, ioaddr+EN0_RCNTHI); + outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO); + outb_p(memaddr >> 8, ioaddr+EN0_RSARHI); + outb_p(E8390_RREAD | E8390_START, ioaddr+E8390_CMD); + insw(ioaddr+NE_DATAPORT, buf, len >> 1); +} +static void __init ne2k_cbus_writemem(struct net_device *dev, int ioaddr, unsigned short memaddr, const char *buf, unsigned short len) +{ + struct ei_device *ei_local = (struct ei_device *)(dev->priv); + outb_p(E8390_NODMA | E8390_START, ioaddr+E8390_CMD); + outb_p(ENISR_RDC, ioaddr+EN0_ISR); + outb_p(len & 0xff, ioaddr+EN0_RCNTLO); + outb_p(len >> 8, ioaddr+EN0_RCNTHI); + outb_p(memaddr & 0xff, ioaddr+EN0_RSARLO); + outb_p(memaddr >> 8, ioaddr+EN0_RSARHI); + outb_p(E8390_RWRITE | E8390_START, ioaddr+E8390_CMD); + outsw(ioaddr+NE_DATAPORT, buf, len >> 1); +} +#endif + +static int ne_probe_cbus(struct net_device *dev, const struct ne2k_cbus_hwinfo *hw, int ioaddr); +/* End of ne2k_cbus.h */ -- cgit v1.2.3 From 1e9df38b59cd6c162416da2744efa178ae90ff56 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:39:47 -0500 Subject: [E1000] Version, copyright, changelog and MAINTAINERS * Version, copyright, changelog and MAINTAINERS updates --- MAINTAINERS | 5 +++-- drivers/net/e1000/e1000.h | 2 +- drivers/net/e1000/e1000_ethtool.c | 2 +- drivers/net/e1000/e1000_hw.c | 2 +- drivers/net/e1000/e1000_hw.h | 2 +- drivers/net/e1000/e1000_main.c | 36 +++++++++++++++++++----------------- drivers/net/e1000/e1000_osdep.h | 2 +- drivers/net/e1000/e1000_param.c | 2 +- 8 files changed, 28 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index f70d80afd2ae..01976bb777e7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -923,10 +923,11 @@ M: scott.feldman@intel.com S: Supported INTEL PRO/1000 GIGABIT ETHERNET SUPPORT -P: Chris Leech -M: christopher.leech@intel.com +P: Jeb Cramer +M: cramerj@intel.com P: Scott Feldman M: scott.feldman@intel.com +W: http://sourceforge.net/projects/e1000/ S: Supported INTERMEZZO FILE SYSTEM diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 18d0c2b5e471..d0cabba03374 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index d06ef79c6e29..5bd4b7ed8951 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 8ead5c6544c8..129ea644a780 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 812dfd140f35..d2d5e3773a32 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 1b66efa8a2b0..30e8fd4213cb 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free @@ -30,7 +30,22 @@ /* Change Log * - * 4.4.19 11/27/02 + * 5.0.43 3/5/03 + * o Feature: Added support for 82541 and 82547 hardware. + * o Feature: Added support for Intel Gigabit PHY (IGP) and a variety of + * eeproms. + * o Feature: Added support for TCP Segmentation Offload (TSO). + * o Feature: Added MII ioctl. + * o Feature: Added support for statistics reporting through ethtool. + * o Cleanup: Removed proprietary hooks for ANS. + * o Cleanup: Miscellaneous code changes to improve CPU utilization. + * - Replaced "%" with conditionals and "+-" operators. + * - Implemented dynamic Interrupt Throttle Rate (ITR). + * - Reduced expensive PCI reads of ICR in interrupt. + * o Bug fix: Request IRQ after descriptor ring setup to avoid panic in + * shared interrupt instances. + * + * 4.4.18 11/27/02 * o Feature: Added user-settable knob for interrupt throttle rate (ITR). * o Cleanup: removed large static array allocations. * o Cleanup: C99 struct initializer format. @@ -42,25 +57,12 @@ * o Bug fix: Make ethtool EEPROM acceses work on older versions of ethtool. * * 4.4.12 10/15/02 - * o Clean up: use members of pci_device rather than direct calls to - * pci_read_config_word. - * o Bug fix: changed default flow control settings. - * o Clean up: ethtool file now has an inclusive list for adapters in the - * Wake-On-LAN capabilities instead of an exclusive list. - * o Bug fix: miscellaneous WoL bug fixes. - * o Added software interrupt for clearing rx ring - * o Bug fix: easier to undo "forcing" of 1000/fd using ethtool. - * o Now setting netdev->mem_end in e1000_probe. - * o Clean up: Moved tx_timeout from interrupt context to process context - * using schedule_task. - * - * 4.3.15 8/9/02 */ char e1000_driver_name[] = "e1000"; char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -char e1000_driver_version[] = "4.4.19-k3"; -char e1000_copyright[] = "Copyright (c) 1999-2002 Intel Corporation."; +char e1000_driver_version[] = "5.0.43-k1"; +char e1000_copyright[] = "Copyright (c) 1999-2003 Intel Corporation."; /* e1000_pci_tbl - PCI Device ID Table * diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index 0d68940f9b98..05b1518aa74d 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index a11941f3f213..bf5ac6b9e7f6 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -1,7 +1,7 @@ /******************************************************************************* - Copyright(c) 1999 - 2002 Intel Corporation. All rights reserved. + Copyright(c) 1999 - 2003 Intel Corporation. All rights reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -- cgit v1.2.3 From 42c675ffb08d3842ae248b47d102a4390f903fbd Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:40:12 -0500 Subject: [E1000] Spd/dplx abstraction; eeprom size changes * Setting speed/duplex is now it's own routine * Update ETHTOOL_GEEPROM routine to use new eeprom size variable --- drivers/net/e1000/e1000_ethtool.c | 33 ++++++--------------------------- drivers/net/e1000/e1000_main.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 5bd4b7ed8951..68a0b371fe0a 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -38,6 +38,7 @@ extern char e1000_driver_version[]; extern int e1000_up(struct e1000_adapter *adapter); extern void e1000_down(struct e1000_adapter *adapter); extern void e1000_reset(struct e1000_adapter *adapter); +extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); static char e1000_gstrings_stats[][ETH_GSTRING_LEN] = { "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", @@ -129,30 +130,9 @@ e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) hw->autoneg = 1; hw->autoneg_advertised = 0x002F; ecmd->advertising = 0x002F; - } else { - hw->autoneg = 0; - switch(ecmd->speed + ecmd->duplex) { - case SPEED_10 + DUPLEX_HALF: - hw->forced_speed_duplex = e1000_10_half; - break; - case SPEED_10 + DUPLEX_FULL: - hw->forced_speed_duplex = e1000_10_full; - break; - case SPEED_100 + DUPLEX_HALF: - hw->forced_speed_duplex = e1000_100_half; - break; - case SPEED_100 + DUPLEX_FULL: - hw->forced_speed_duplex = e1000_100_full; - break; - case SPEED_1000 + DUPLEX_FULL: - hw->autoneg = 1; - hw->autoneg_advertised = ADVERTISE_1000_FULL; - break; - case SPEED_1000 + DUPLEX_HALF: /* not supported */ - default: + } else + if(e1000_set_spd_dplx(adapter, ecmd->speed + ecmd->duplex)) return -EINVAL; - } - } /* reset the link */ @@ -542,13 +522,12 @@ e1000_ethtool_ioctl(struct net_device *netdev, struct ifreq *ifr) } case ETHTOOL_GEEPROM: { struct ethtool_eeprom eeprom = {ETHTOOL_GEEPROM}; + struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; void *ptr; - int max_len, err = 0; - - max_len = e1000_eeprom_size(&adapter->hw); + int err = 0; - eeprom_buff = kmalloc(max_len, GFP_KERNEL); + eeprom_buff = kmalloc(hw->eeprom.word_size * 2, GFP_KERNEL); if(eeprom_buff == NULL) return -ENOMEM; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 30e8fd4213cb..442037ba44ae 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -123,6 +123,7 @@ static char *e1000_strings[] = { int e1000_up(struct e1000_adapter *adapter); void e1000_down(struct e1000_adapter *adapter); void e1000_reset(struct e1000_adapter *adapter); +int e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx); static int e1000_init_module(void); static void e1000_exit_module(void); @@ -2404,6 +2405,35 @@ e1000_restore_vlan(struct e1000_adapter *adapter) } } +int +e1000_set_spd_dplx(struct e1000_adapter *adapter, uint16_t spddplx) +{ + adapter->hw.autoneg = 0; + + switch(spddplx) { + case SPEED_10 + DUPLEX_HALF: + adapter->hw.forced_speed_duplex = e1000_10_half; + break; + case SPEED_10 + DUPLEX_FULL: + adapter->hw.forced_speed_duplex = e1000_10_full; + break; + case SPEED_100 + DUPLEX_HALF: + adapter->hw.forced_speed_duplex = e1000_100_half; + break; + case SPEED_100 + DUPLEX_FULL: + adapter->hw.forced_speed_duplex = e1000_100_full; + break; + case SPEED_1000 + DUPLEX_FULL: + adapter->hw.autoneg = 1; + adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; + break; + case SPEED_1000 + DUPLEX_HALF: /* not supported */ + default: + return -EINVAL; + } + return 0; +} + static int e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) { -- cgit v1.2.3 From 5f3529cce14d68491dced89efb4f4c7b14f80317 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:40:37 -0500 Subject: [E1000] IRQ registration fix * Fixed IRQ registration bug; IRQ now registered after resources are acquired --- drivers/net/e1000/e1000_main.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 442037ba44ae..7c39f533479d 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -252,13 +252,10 @@ e1000_up(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; - if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, - netdev->name, netdev)) - return -1; - /* hardware has been reset, we need to reload some things */ e1000_set_multi(netdev); + e1000_restore_vlan(adapter); e1000_configure_tx(adapter); @@ -266,6 +263,14 @@ e1000_up(struct e1000_adapter *adapter) e1000_configure_rx(adapter); e1000_alloc_rx_buffers(adapter); + if(request_irq(netdev->irq, &e1000_intr, SA_SHIRQ | SA_SAMPLE_RANDOM, + netdev->name, netdev)) { + e1000_reset_hw(&adapter->hw); + e1000_free_tx_resources(adapter); + e1000_free_rx_resources(adapter); + return -1; + } + mod_timer(&adapter->watchdog_timer, jiffies); e1000_irq_enable(adapter); -- cgit v1.2.3 From 908a658e9a484d5ddec9a773121ec1bd0f62e112 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:41:10 -0500 Subject: [E1000] Added 82541 & 82547 support * Added support for 82541 and 82547 gigabit ethernet adapters --- drivers/net/Kconfig | 1 + drivers/net/e1000/e1000.h | 18 +- drivers/net/e1000/e1000_ethtool.c | 63 +- drivers/net/e1000/e1000_hw.c | 1377 ++++++++++++++++++++++++++++++------- drivers/net/e1000/e1000_hw.h | 259 ++++++- drivers/net/e1000/e1000_main.c | 210 +++++- 6 files changed, 1608 insertions(+), 320 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d770d320577f..243b717f107a 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1904,6 +1904,7 @@ config E1000 82544 PRO/1000 XF Server Adapter A50484-xxx 82544 PRO/1000 T Desktop Adapter A62947-xxx 82540 PRO/1000 MT Desktop Adapter A78408-xxx + 82541 PRO/1000 MT Desktop Adapter C91016-xxx 82545 PRO/1000 MT Server Adapter A92165-xxx 82546 PRO/1000 MT Dual Port Server Adapter A92111-xxx 82545 PRO/1000 MF Server Adapter A91622-xxx diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index d0cabba03374..9efac9fc6775 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -95,6 +95,15 @@ struct e1000_adapter; #define E1000_RXBUFFER_8192 8192 #define E1000_RXBUFFER_16384 16384 +/* SmartSpeed delimiters */ +#define E1000_SMARTSPEED_DOWNSHIFT 3 +#define E1000_SMARTSPEED_MAX 15 + +/* Packet Buffer allocations */ +#define E1000_TX_FIFO_SIZE_SHIFT 0xA +#define E1000_TX_HEAD_ADDR_SHIFT 7 +#define E1000_PBA_TX_MASK 0xFFFF0000 + /* Flow Control High-Watermark: 43464 bytes */ #define E1000_FC_HIGH_THRESH 0xA9C8 @@ -109,9 +118,6 @@ struct e1000_adapter; /* How many Rx Buffers do we bundle into one write to the hardware ? */ #define E1000_RX_BUFFER_WRITE 16 -#define E1000_JUMBO_PBA 0x00000028 -#define E1000_DEFAULT_PBA 0x00000030 - #define AUTO_ALL_MODES 0 #define E1000_EEPROM_APME 4 @@ -155,6 +161,7 @@ struct e1000_desc_ring { /* board specific private data structure */ struct e1000_adapter { + struct timer_list tx_fifo_stall_timer; struct timer_list watchdog_timer; struct timer_list phy_info_timer; struct vlan_group *vlgrp; @@ -163,6 +170,7 @@ struct e1000_adapter { uint32_t rx_buffer_len; uint32_t part_num; uint32_t wol; + uint32_t smartspeed; uint16_t link_speed; uint16_t link_duplex; spinlock_t stats_lock; @@ -178,6 +186,10 @@ struct e1000_adapter { uint32_t tx_int_delay; uint32_t tx_abs_int_delay; int max_data_per_txd; + uint32_t tx_fifo_head; + uint32_t tx_head_addr; + uint32_t tx_fifo_size; + atomic_t tx_fifo_stall; /* RX */ struct e1000_desc_ring rx_ring; diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 68a0b371fe0a..426101fa0a2b 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -145,16 +145,6 @@ e1000_ethtool_sset(struct e1000_adapter *adapter, struct ethtool_cmd *ecmd) return 0; } -static inline int -e1000_eeprom_size(struct e1000_hw *hw) -{ - if((hw->mac_type > e1000_82544) && - (E1000_READ_REG(hw, EECD) & E1000_EECD_SIZE)) - return 512; - else - return 128; -} - static void e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, struct ethtool_drvinfo *drvinfo) @@ -166,7 +156,7 @@ e1000_ethtool_gdrvinfo(struct e1000_adapter *adapter, drvinfo->n_stats = E1000_STATS_LEN; #define E1000_REGS_LEN 32 drvinfo->regdump_len = E1000_REGS_LEN * sizeof(uint32_t); - drvinfo->eedump_len = e1000_eeprom_size(&adapter->hw); + drvinfo->eedump_len = adapter->hw.eeprom.word_size * 2; } static void @@ -200,9 +190,8 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter, struct ethtool_eeprom *eeprom, uint16_t *eeprom_buff) { struct e1000_hw *hw = &adapter->hw; - int max_len, first_word, last_word; + int first_word, last_word; int ret_val = 0; - int i; if(eeprom->len == 0) { ret_val = -EINVAL; @@ -211,22 +200,28 @@ e1000_ethtool_geeprom(struct e1000_adapter *adapter, eeprom->magic = hw->vendor_id | (hw->device_id << 16); - max_len = e1000_eeprom_size(hw); - if(eeprom->offset > eeprom->offset + eeprom->len) { ret_val = -EINVAL; goto geeprom_error; } - if((eeprom->offset + eeprom->len) > max_len) - eeprom->len = (max_len - eeprom->offset); + if((eeprom->offset + eeprom->len) > (hw->eeprom.word_size * 2)) + eeprom->len = ((hw->eeprom.word_size * 2) - eeprom->offset); first_word = eeprom->offset >> 1; last_word = (eeprom->offset + eeprom->len - 1) >> 1; - for(i = 0; i <= (last_word - first_word); i++) - e1000_read_eeprom(hw, first_word + i, &eeprom_buff[i]); - + if(hw->eeprom.type == e1000_eeprom_spi) + ret_val = e1000_read_eeprom(hw, first_word, + last_word - first_word + 1, + eeprom_buff); + else { + uint16_t i; + for (i = 0; i < last_word - first_word + 1; i++) + if((ret_val = e1000_read_eeprom(hw, first_word + i, 1, + &eeprom_buff[i]))) + break; + } geeprom_error: return ret_val; } @@ -237,9 +232,8 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, { struct e1000_hw *hw = &adapter->hw; uint16_t *eeprom_buff; - int max_len, first_word, last_word; void *ptr; - int i; + int max_len, first_word, last_word, ret_val = 0; if(eeprom->len == 0) return -EOPNOTSUPP; @@ -247,7 +241,7 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, if(eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) return -EFAULT; - max_len = e1000_eeprom_size(hw); + max_len = hw->eeprom.word_size * 2; if((eeprom->offset + eeprom->len) > max_len) eeprom->len = (max_len - eeprom->offset); @@ -263,30 +257,31 @@ e1000_ethtool_seeprom(struct e1000_adapter *adapter, if(eeprom->offset & 1) { /* need read/modify/write of first changed EEPROM word */ /* only the second byte of the word is being modified */ - e1000_read_eeprom(hw, first_word, &eeprom_buff[0]); + ret_val = e1000_read_eeprom(hw, first_word, 1, + &eeprom_buff[0]); ptr++; } - if((eeprom->offset + eeprom->len) & 1) { + if(((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { /* need read/modify/write of last changed EEPROM word */ /* only the first byte of the word is being modified */ - e1000_read_eeprom(hw, last_word, + ret_val = e1000_read_eeprom(hw, last_word, 1, &eeprom_buff[last_word - first_word]); } - if(copy_from_user(ptr, user_data, eeprom->len)) { - kfree(eeprom_buff); - return -EFAULT; + if((ret_val != 0) || copy_from_user(ptr, user_data, eeprom->len)) { + ret_val = -EFAULT; + goto seeprom_error; } - for(i = 0; i <= (last_word - first_word); i++) - e1000_write_eeprom(hw, first_word + i, eeprom_buff[i]); + ret_val = e1000_write_eeprom(hw, first_word, + last_word - first_word + 1, eeprom_buff); /* Update the checksum over the first part of the EEPROM if needed */ - if(first_word <= EEPROM_CHECKSUM_REG) + if((ret_val == 0) && first_word <= EEPROM_CHECKSUM_REG) e1000_update_eeprom_checksum(hw); +seeprom_error: kfree(eeprom_buff); - - return 0; + return ret_val; } static void diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 129ea644a780..56b315bc00a9 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -32,6 +32,8 @@ #include "e1000_hw.h" +static int32_t e1000_set_phy_type(struct e1000_hw *hw); +static void e1000_phy_init_script(struct e1000_hw *hw); static int32_t e1000_setup_fiber_link(struct e1000_hw *hw); static int32_t e1000_setup_copper_link(struct e1000_hw *hw); static int32_t e1000_phy_force_speed_duplex(struct e1000_hw *hw); @@ -42,19 +44,103 @@ static void e1000_lower_mdi_clk(struct e1000_hw *hw, uint32_t *ctrl); static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t data, uint16_t count); static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw); static int32_t e1000_phy_reset_dsp(struct e1000_hw *hw); +static int32_t e1000_write_eeprom_spi(struct e1000_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data); +static int32_t e1000_write_eeprom_microwire(struct e1000_hw *hw, + uint16_t offset, uint16_t words, + uint16_t *data); +static int32_t e1000_spi_eeprom_ready(struct e1000_hw *hw); static void e1000_raise_ee_clk(struct e1000_hw *hw, uint32_t *eecd); static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd); static void e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count); -static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw); -static void e1000_setup_eeprom(struct e1000_hw *hw); -static void e1000_clock_eeprom(struct e1000_hw *hw); -static void e1000_cleanup_eeprom(struct e1000_hw *hw); +static uint16_t e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count); +static int32_t e1000_acquire_eeprom(struct e1000_hw *hw); +static void e1000_release_eeprom(struct e1000_hw *hw); static void e1000_standby_eeprom(struct e1000_hw *hw); static int32_t e1000_id_led_init(struct e1000_hw * hw); + + +/****************************************************************************** + * Set the phy type member in the hw struct. + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +int32_t +e1000_set_phy_type(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_set_phy_type"); + + switch(hw->phy_id) { + case M88E1000_E_PHY_ID: + case M88E1000_I_PHY_ID: + case M88E1011_I_PHY_ID: + hw->phy_type = e1000_phy_m88; + break; + case IGP01E1000_I_PHY_ID: + hw->phy_type = e1000_phy_igp; + break; + default: + /* Should never have loaded on this device */ + hw->phy_type = e1000_phy_undefined; + return -E1000_ERR_PHY_TYPE; + } + + return E1000_SUCCESS; +} + +/****************************************************************************** + * IGP phy init script - initializes the GbE PHY + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +static void +e1000_phy_init_script(struct e1000_hw *hw) +{ + DEBUGFUNC("e1000_phy_init_script"); + + if(hw->phy_init_script) { + msec_delay(10); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); + e1000_write_phy_reg(hw,0x0000,0x0140); + + msec_delay(5); + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F95); + e1000_write_phy_reg(hw,0x0015,0x0001); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F71); + e1000_write_phy_reg(hw,0x0011,0xBD21); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F79); + e1000_write_phy_reg(hw,0x0019,0x0018); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F30); + e1000_write_phy_reg(hw,0x0010,0x1600); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F31); + e1000_write_phy_reg(hw,0x0011,0x0014); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F32); + e1000_write_phy_reg(hw,0x0012,0x161C); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F94); + e1000_write_phy_reg(hw,0x0014,0x0003); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x1F96); + e1000_write_phy_reg(hw,0x0016,0x003F); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x2010); + e1000_write_phy_reg(hw,0x0010,0x0008); + + e1000_write_phy_reg(hw,IGP01E1000_PHY_PAGE_SELECT,0x0000); + e1000_write_phy_reg(hw,0x0000,0x3300); + } +} + /****************************************************************************** * Set the mac type member in the hw struct. - * + * * hw - Struct containing variables accessed by shared code *****************************************************************************/ int32_t @@ -101,10 +187,19 @@ e1000_set_mac_type(struct e1000_hw *hw) case E1000_DEV_ID_82546EB_FIBER: hw->mac_type = e1000_82546; break; + case E1000_DEV_ID_82541EI: + case E1000_DEV_ID_82541EP: + hw->mac_type = e1000_82541; + break; + case E1000_DEV_ID_82547EI: + hw->mac_type = e1000_82547; + break; default: /* Should never have loaded on this device */ return -E1000_ERR_MAC_TYPE; } + + return E1000_SUCCESS; } /****************************************************************************** @@ -119,9 +214,10 @@ e1000_reset_hw(struct e1000_hw *hw) uint32_t ctrl_ext; uint32_t icr; uint32_t manc; + uint32_t led_ctrl; DEBUGFUNC("e1000_reset_hw"); - + /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ if(hw->mac_type == e1000_82542_rev2_0) { DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); @@ -156,6 +252,12 @@ e1000_reset_hw(struct e1000_hw *hw) DEBUGOUT("Issuing a global reset to MAC\n"); ctrl = E1000_READ_REG(hw, CTRL); + /* Must reset the PHY before resetting the MAC */ + if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { + E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_PHY_RST)); + msec_delay(5); + } + if(hw->mac_type > e1000_82543) E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); else @@ -173,13 +275,25 @@ e1000_reset_hw(struct e1000_hw *hw) msec_delay(2); } else { /* Wait for EEPROM reload (it happens automatically) */ - msec_delay(4); + msec_delay(5); /* Dissable HW ARPs on ASF enabled adapters */ manc = E1000_READ_REG(hw, MANC); manc &= ~(E1000_MANC_ARP_EN); E1000_WRITE_REG(hw, MANC, manc); } - + + if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { + e1000_phy_init_script(hw); + + /* Configure activity LED after PHY reset */ + led_ctrl = E1000_READ_REG(hw, LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= IGP_ACTIVITY_LED_ENABLE; + if(hw->mac_type == e1000_82547) + led_ctrl |= IGP_LED3_MODE; + E1000_WRITE_REG(hw, LEDCTL, led_ctrl); + } + /* Clear interrupt mask to stop board from generating interrupts */ DEBUGOUT("Masking off all interrupts\n"); E1000_WRITE_REG(hw, IMC, 0xffffffff); @@ -353,7 +467,7 @@ e1000_setup_link(struct e1000_hw *hw) * control setting, then the variable hw->fc will * be initialized based on a value in the EEPROM. */ - if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data) < 0) { + if(e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -571,10 +685,10 @@ e1000_setup_fiber_link(struct e1000_hw *hw) * * hw - Struct containing variables accessed by shared code ******************************************************************************/ -static int32_t +static int32_t e1000_setup_copper_link(struct e1000_hw *hw) { - uint32_t ctrl; + uint32_t ctrl, led_ctrl; int32_t ret_val; uint16_t i; uint16_t phy_data; @@ -604,6 +718,69 @@ e1000_setup_copper_link(struct e1000_hw *hw) } DEBUGOUT1("Phy ID = %x \n", hw->phy_id); +if (hw->phy_type == e1000_phy_igp) { + + ret_val = e1000_phy_reset(hw); + if(ret_val < 0) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } + + /* Wait 10ms for MAC to configure PHY from eeprom settings */ + msec_delay(15); + + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + + /* Configure activity LED after PHY reset */ + led_ctrl = E1000_READ_REG(hw, LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= IGP_ACTIVITY_LED_ENABLE; + if(hw->mac_type == e1000_82547) + led_ctrl |= IGP_LED3_MODE; + E1000_WRITE_REG(hw, LEDCTL, led_ctrl); + + if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { + /* Disable SmartSpeed */ + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + /* Set auto Master/Slave resolution process */ + if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data &= ~CR_1000T_MS_ENABLE; + if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + } + + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + + /* Force MDI for IGP PHY */ + phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | IGP01E1000_PSCR_FORCE_MDI_MDIX); + + hw->mdix = 1; + + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + +} else { /* Enable CRS on TX. This must be set for half-duplex operation. */ if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); @@ -677,7 +854,8 @@ e1000_setup_copper_link(struct e1000_hw *hw) DEBUGOUT("Error Resetting the PHY\n"); return ret_val; } - +} + /* Options: * autoneg = 1 (default) * PHY will advertise value(s) parsed from @@ -736,6 +914,7 @@ e1000_setup_copper_link(struct e1000_hw *hw) return ret_val; } } + hw->get_link_status = TRUE; } else { DEBUGOUT("Forcing speed and duplex\n"); ret_val = e1000_phy_force_speed_duplex(hw); @@ -1014,6 +1193,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); +if (hw->phy_type == e1000_phy_m88) { if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; @@ -1031,6 +1211,23 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) /* Need to reset the PHY or these changes will be ignored */ mii_ctrl_reg |= MII_CR_RESET; +} else { + /* Clear Auto-Crossover to force MDI manually. IGP requires MDI + * forced whenever speed or duplex are forced. + */ + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + + phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; + phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; + + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } +} /* Write back the modified PHY MII control register. */ if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) { @@ -1093,7 +1290,8 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) } } } - + +if (hw->phy_type == e1000_phy_m88) { /* Because we reset the PHY above, we need to re-force TX_CLK in the * Extended PHY Specific Control Register to 25MHz clock. This value * defaults back to a 2.5MHz clock when the PHY is reset. @@ -1120,6 +1318,7 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) DEBUGOUT("PHY Write Error\n"); return -E1000_ERR_PHY; } +} return 0; } @@ -1136,6 +1335,8 @@ e1000_config_collision_dist(struct e1000_hw *hw) { uint32_t tctl; + DEBUGFUNC("e1000_config_collision_dist"); + tctl = E1000_READ_REG(hw, TCTL); tctl &= ~E1000_TCTL_COLD; @@ -1172,6 +1373,26 @@ e1000_config_mac_to_phy(struct e1000_hw *hw) /* Set up duplex in the Device Control and Transmit Control * registers depending on negotiated values. */ +if (hw->phy_type == e1000_phy_igp) { + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; + else ctrl &= ~E1000_CTRL_FD; + + e1000_config_collision_dist(hw); + + /* Set up speed in the Device Control register depending on + * negotiated values. + */ + if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) + ctrl |= E1000_CTRL_SPD_1000; + else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_100MBPS) + ctrl |= E1000_CTRL_SPD_100; +} else { if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; @@ -1188,6 +1409,7 @@ e1000_config_mac_to_phy(struct e1000_hw *hw) ctrl |= E1000_CTRL_SPD_1000; else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) ctrl |= E1000_CTRL_SPD_100; +} /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); return 0; @@ -1519,6 +1741,10 @@ e1000_check_for_link(struct e1000_hw *hw) if(phy_data & MII_SR_LINK_STATUS) { hw->get_link_status = FALSE; + /* Check if there was DownShift, must be checked immediately after + * link-up */ + e1000_check_downshift(hw); + } else { /* No link detected */ return 0; @@ -2021,8 +2247,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, void e1000_phy_hw_reset(struct e1000_hw *hw) { - uint32_t ctrl; - uint32_t ctrl_ext; + uint32_t ctrl, ctrl_ext, led_ctrl; DEBUGFUNC("e1000_phy_hw_reset"); @@ -2053,6 +2278,21 @@ e1000_phy_hw_reset(struct e1000_hw *hw) E1000_WRITE_FLUSH(hw); } udelay(150); + + if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { + DEBUGOUT("PHY Write Error\n"); + return; + } + + /* Configure activity LED after PHY reset */ + led_ctrl = E1000_READ_REG(hw, LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= IGP_ACTIVITY_LED_ENABLE; + if(hw->mac_type == e1000_82547) + led_ctrl |= IGP_LED3_MODE; + E1000_WRITE_REG(hw, LEDCTL, led_ctrl); + } } /****************************************************************************** @@ -2079,6 +2319,9 @@ e1000_phy_reset(struct e1000_hw *hw) return -E1000_ERR_PHY; } udelay(1); + if (hw->phy_type == e1000_phy_igp) { + e1000_phy_init_script(hw); + } return 0; } @@ -2092,6 +2335,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw) { uint16_t phy_id_high, phy_id_low; boolean_t match = FALSE; + int32_t phy_init_status; DEBUGFUNC("e1000_detect_gig_phy"); @@ -2101,7 +2345,7 @@ e1000_detect_gig_phy(struct e1000_hw *hw) return -E1000_ERR_PHY; } hw->phy_id = (uint32_t) (phy_id_high << 16); - udelay(2); + udelay(20); if(e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; @@ -2121,11 +2365,17 @@ e1000_detect_gig_phy(struct e1000_hw *hw) case e1000_82546: if(hw->phy_id == M88E1011_I_PHY_ID) match = TRUE; break; + case e1000_82541: + case e1000_82547: + if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE; + break; default: DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type); return -E1000_ERR_CONFIG; } - if(match) { + phy_init_status = e1000_set_phy_type(hw); + + if ((match) && (phy_init_status == E1000_SUCCESS)) { DEBUGOUT1("PHY ID 0x%X detected\n", hw->phy_id); return 0; } @@ -2155,6 +2405,133 @@ e1000_phy_reset_dsp(struct e1000_hw *hw) return ret_val; } +/****************************************************************************** +* Get PHY information from various PHY registers for igp PHY only. +* +* hw - Struct containing variables accessed by shared code +* phy_info - PHY information structure +******************************************************************************/ +int32_t +e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) +{ + uint16_t phy_data, polarity, min_length, max_length, average; + + DEBUGFUNC("e1000_phy_igp_get_info"); + + /* The downshift status is checked only once, after link is established, + * and it stored in the hw->speed_downgraded parameter. */ + phy_info->downshift = hw->speed_downgraded; + + /* IGP01E1000 does not need to support it. */ + phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal; + + /* IGP01E1000 always correct polarity reversal */ + phy_info->polarity_correction = e1000_polarity_reversal_enabled; + + /* Check polarity status */ + if(e1000_check_polarity(hw, &polarity) < 0) + return -E1000_ERR_PHY; + + phy_info->cable_polarity = polarity; + + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) + return -E1000_ERR_PHY; + + phy_info->mdix_mode = (phy_data & IGP01E1000_PSSR_MDIX) >> + IGP01E1000_PSSR_MDIX_SHIFT; + + if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) { + /* Local/Remote Receiver Information are only valid at 1000 Mbps */ + if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) + return -E1000_ERR_PHY; + + phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> + SR_1000T_LOCAL_RX_STATUS_SHIFT; + phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >> + SR_1000T_REMOTE_RX_STATUS_SHIFT; + + /* Get cable length */ + if(e1000_get_cable_length(hw, &min_length, &max_length) < 0) + return -E1000_ERR_PHY; + + /* transalte to old method */ + average = (max_length + min_length) / 2; + + if(average <= e1000_igp_cable_length_50) + phy_info->cable_length = e1000_cable_length_50; + else if(average <= e1000_igp_cable_length_80) + phy_info->cable_length = e1000_cable_length_50_80; + else if(average <= e1000_igp_cable_length_110) + phy_info->cable_length = e1000_cable_length_80_110; + else if(average <= e1000_igp_cable_length_140) + phy_info->cable_length = e1000_cable_length_110_140; + else + phy_info->cable_length = e1000_cable_length_140; + } + + return E1000_SUCCESS; +} + +/****************************************************************************** +* Get PHY information from various PHY registers fot m88 PHY only. +* +* hw - Struct containing variables accessed by shared code +* phy_info - PHY information structure +******************************************************************************/ +int32_t +e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) +{ + uint16_t phy_data, polarity; + + DEBUGFUNC("e1000_phy_m88_get_info"); + + /* The downshift status is checked only once, after link is established, + * and it stored in the hw->speed_downgraded parameter. */ + phy_info->downshift = hw->speed_downgraded; + + if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) + return -E1000_ERR_PHY; + + phy_info->extended_10bt_distance = + (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> + M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT; + phy_info->polarity_correction = + (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >> + M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; + + /* Check polarity status */ + if(e1000_check_polarity(hw, &polarity) < 0) + return -E1000_ERR_PHY; + + phy_info->cable_polarity = polarity; + + if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) + return -E1000_ERR_PHY; + + phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> + M88E1000_PSSR_MDIX_SHIFT; + + if(phy_data & M88E1000_PSSR_1000MBS) { + /* Cable Length Estimation and Local/Remote Receiver Informatoion + * are only valid at 1000 Mbps + */ + phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + M88E1000_PSSR_CABLE_LENGTH_SHIFT); + + if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) + return -E1000_ERR_PHY; + + phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> + SR_1000T_LOCAL_RX_STATUS_SHIFT; + + phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >> + SR_1000T_REMOTE_RX_STATUS_SHIFT; + } + + return E1000_SUCCESS; +} + /****************************************************************************** * Get PHY information from various PHY registers * @@ -2165,7 +2542,6 @@ int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) { - int32_t ret_val = -E1000_ERR_PHY; uint16_t phy_data; DEBUGFUNC("e1000_phy_get_info"); @@ -2173,6 +2549,7 @@ e1000_phy_get_info(struct e1000_hw *hw, phy_info->cable_length = e1000_cable_length_undefined; phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined; phy_info->cable_polarity = e1000_rev_polarity_undefined; + phy_info->downshift = e1000_downshift_undefined; phy_info->polarity_correction = e1000_polarity_reversal_undefined; phy_info->mdix_mode = e1000_auto_x_mode_undefined; phy_info->local_rx = e1000_1000t_rx_status_undefined; @@ -2183,47 +2560,23 @@ e1000_phy_get_info(struct e1000_hw *hw, return -E1000_ERR_CONFIG; } - do { - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) break; - if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) break; - if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { - DEBUGOUT("PHY info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) - break; - phy_info->extended_10bt_distance = - (phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> - M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT; - phy_info->polarity_correction = - (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >> - M88E1000_PSCR_POLARITY_REVERSAL_SHIFT; - - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) - break; - phy_info->cable_polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >> - M88E1000_PSSR_REV_POLARITY_SHIFT; - phy_info->mdix_mode = (phy_data & M88E1000_PSSR_MDIX) >> - M88E1000_PSSR_MDIX_SHIFT; - if(phy_data & M88E1000_PSSR_1000MBS) { - /* Cable Length Estimation and Local/Remote Receiver Informatoion - * are only valid at 1000 Mbps - */ - phy_info->cable_length = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT); - if(e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data) < 0) - break; - phy_info->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) >> - SR_1000T_LOCAL_RX_STATUS_SHIFT; - phy_info->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) >> - SR_1000T_REMOTE_RX_STATUS_SHIFT; - } - ret_val = 0; - } while(0); + if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + if(e1000_read_phy_reg(hw, PHY_STATUS, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + if((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { + DEBUGOUT("PHY info is only valid if link is up\n"); + return -E1000_ERR_CONFIG; + } - if(ret_val < 0) DEBUGOUT("PHY Read Error\n"); - return ret_val; + if (hw->phy_type == e1000_phy_igp) + return e1000_phy_igp_get_info(hw, phy_info); + else + return e1000_phy_m88_get_info(hw, phy_info); } int32_t @@ -2239,6 +2592,109 @@ e1000_validate_mdi_setting(struct e1000_hw *hw) return 0; } + +/****************************************************************************** + * Sets up eeprom variables in the hw struct. Must be called after mac_type + * is configured. + * + * hw - Struct containing variables accessed by shared code + *****************************************************************************/ +void +e1000_init_eeprom_params(struct e1000_hw *hw) +{ + struct e1000_eeprom_info *eeprom = &hw->eeprom; + uint32_t eecd = E1000_READ_REG(hw, EECD); + uint16_t eeprom_size; + + DEBUGFUNC("e1000_init_eeprom_params"); + + switch (hw->mac_type) { + case e1000_82542_rev2_0: + case e1000_82542_rev2_1: + case e1000_82543: + case e1000_82544: + eeprom->type = e1000_eeprom_microwire; + eeprom->word_size = 64; + eeprom->opcode_bits = 3; + eeprom->address_bits = 6; + eeprom->delay_usec = 50; + break; + case e1000_82540: + case e1000_82545: + case e1000_82546: + eeprom->type = e1000_eeprom_microwire; + eeprom->opcode_bits = 3; + eeprom->delay_usec = 50; + if(eecd & E1000_EECD_SIZE) { + eeprom->word_size = 256; + eeprom->address_bits = 8; + } else { + eeprom->word_size = 64; + eeprom->address_bits = 6; + } + break; + case e1000_82541: + case e1000_82547: + default: + if (eecd & E1000_EECD_TYPE) { + eeprom->type = e1000_eeprom_spi; + eeprom->opcode_bits = 8; + eeprom->delay_usec = 1; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->page_size = 32; + eeprom->address_bits = 16; + } else { + eeprom->page_size = 8; + eeprom->address_bits = 8; + } + } else { + eeprom->type = e1000_eeprom_microwire; + eeprom->opcode_bits = 3; + eeprom->delay_usec = 50; + if (eecd & E1000_EECD_ADDR_BITS) { + eeprom->word_size = 256; + eeprom->address_bits = 8; + } else { + eeprom->word_size = 64; + eeprom->address_bits = 6; + } + } + break; + } + + if (eeprom->type == e1000_eeprom_spi) { + eeprom->word_size = 64; + if (e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size) == 0) { + eeprom_size &= EEPROM_SIZE_MASK; + + switch (eeprom_size) { + case EEPROM_SIZE_16KB: + eeprom->word_size = 8192; + break; + case EEPROM_SIZE_8KB: + eeprom->word_size = 4096; + break; + case EEPROM_SIZE_4KB: + eeprom->word_size = 2048; + break; + case EEPROM_SIZE_2KB: + eeprom->word_size = 1024; + break; + case EEPROM_SIZE_1KB: + eeprom->word_size = 512; + break; + case EEPROM_SIZE_512B: + eeprom->word_size = 256; + break; + case EEPROM_SIZE_128B: + default: + eeprom->word_size = 64; + break; + } + } + } +} + /****************************************************************************** * Raises the EEPROM's clock input. * @@ -2255,26 +2711,26 @@ e1000_raise_ee_clk(struct e1000_hw *hw, *eecd = *eecd | E1000_EECD_SK; E1000_WRITE_REG(hw, EECD, *eecd); E1000_WRITE_FLUSH(hw); - udelay(50); + udelay(hw->eeprom.delay_usec); } /****************************************************************************** * Lowers the EEPROM's clock input. * - * hw - Struct containing variables accessed by shared code + * hw - Struct containing variables accessed by shared code * eecd - EECD's current value *****************************************************************************/ static void e1000_lower_ee_clk(struct e1000_hw *hw, uint32_t *eecd) { - /* Lower the clock input to the EEPROM (by clearing the SK bit), and then - * wait 50 microseconds. + /* Lower the clock input to the EEPROM (by clearing the SK bit), and then + * wait 50 microseconds. */ *eecd = *eecd & ~E1000_EECD_SK; E1000_WRITE_REG(hw, EECD, *eecd); E1000_WRITE_FLUSH(hw); - udelay(50); + udelay(hw->eeprom.delay_usec); } /****************************************************************************** @@ -2289,16 +2745,21 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw, uint16_t data, uint16_t count) { + struct e1000_eeprom_info *eeprom = &hw->eeprom; uint32_t eecd; uint32_t mask; /* We need to shift "count" bits out to the EEPROM. So, value in the * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. + * In order to do this, "data" must be broken down into bits. */ mask = 0x01 << (count - 1); eecd = E1000_READ_REG(hw, EECD); - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); + if (eeprom->type == e1000_eeprom_microwire) { + eecd &= ~E1000_EECD_DO; + } else if (eeprom->type == e1000_eeprom_spi) { + eecd |= E1000_EECD_DO; + } do { /* A "1" is shifted out to the EEPROM by setting bit "DI" to a "1", * and then raising and then lowering the clock (the SK bit controls @@ -2313,7 +2774,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw, E1000_WRITE_REG(hw, EECD, eecd); E1000_WRITE_FLUSH(hw); - udelay(50); + udelay(eeprom->delay_usec); e1000_raise_ee_clk(hw, &eecd); e1000_lower_ee_clk(hw, &eecd); @@ -2333,7 +2794,7 @@ e1000_shift_out_ee_bits(struct e1000_hw *hw, * hw - Struct containing variables accessed by shared code *****************************************************************************/ static uint16_t -e1000_shift_in_ee_bits(struct e1000_hw *hw) +e1000_shift_in_ee_bits(struct e1000_hw *hw, uint16_t count) { uint32_t eecd; uint32_t i; @@ -2351,7 +2812,7 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw) eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); data = 0; - for(i = 0; i < 16; i++) { + for(i = 0; i < count; i++) { data = data << 1; e1000_raise_ee_clk(hw, &eecd); @@ -2372,104 +2833,196 @@ e1000_shift_in_ee_bits(struct e1000_hw *hw) * * hw - Struct containing variables accessed by shared code * - * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This + * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This * function should be called before issuing a command to the EEPROM. *****************************************************************************/ -static void -e1000_setup_eeprom(struct e1000_hw *hw) +static int32_t +e1000_acquire_eeprom(struct e1000_hw *hw) { - uint32_t eecd; + struct e1000_eeprom_info *eeprom = &hw->eeprom; + uint32_t eecd, i=0; + + DEBUGFUNC("e1000_acquire_eeprom"); eecd = E1000_READ_REG(hw, EECD); - /* Clear SK and DI */ - eecd &= ~(E1000_EECD_SK | E1000_EECD_DI); - E1000_WRITE_REG(hw, EECD, eecd); + /* Request EEPROM Access */ + if(hw->mac_type > e1000_82544) { + eecd |= E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + eecd = E1000_READ_REG(hw, EECD); + while((!(eecd & E1000_EECD_GNT)) && + (i < E1000_EEPROM_GRANT_ATTEMPTS)) { + i++; + udelay(5); + eecd = E1000_READ_REG(hw, EECD); + } + if(!(eecd & E1000_EECD_GNT)) { + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + DEBUGOUT("Could not acquire EEPROM grant\n"); + return -E1000_ERR_EEPROM; + } + } - /* Set CS */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, EECD, eecd); + /* Setup EEPROM for Read/Write */ + + if (eeprom->type == e1000_eeprom_microwire) { + /* Clear SK and DI */ + eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); + E1000_WRITE_REG(hw, EECD, eecd); + + /* Set CS */ + eecd |= E1000_EECD_CS; + E1000_WRITE_REG(hw, EECD, eecd); + } else if (eeprom->type == e1000_eeprom_spi) { + /* Clear SK and CS */ + eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); + E1000_WRITE_REG(hw, EECD, eecd); + udelay(1); + } + + return E1000_SUCCESS; } /****************************************************************************** * Returns EEPROM to a "standby" state - * + * * hw - Struct containing variables accessed by shared code *****************************************************************************/ static void e1000_standby_eeprom(struct e1000_hw *hw) { + struct e1000_eeprom_info *eeprom = &hw->eeprom; uint32_t eecd; eecd = E1000_READ_REG(hw, EECD); - /* Deselct EEPROM */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); + if(eeprom->type == e1000_eeprom_microwire) { + eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(eeprom->delay_usec); - /* Clock high */ - eecd |= E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); + /* Clock high */ + eecd |= E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(eeprom->delay_usec); - /* Select EEPROM */ - eecd |= E1000_EECD_CS; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); + /* Select EEPROM */ + eecd |= E1000_EECD_CS; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(eeprom->delay_usec); - /* Clock low */ - eecd &= ~E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); + /* Clock low */ + eecd &= ~E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(eeprom->delay_usec); + } else if(eeprom->type == e1000_eeprom_spi) { + /* Toggle CS to flush commands */ + eecd |= E1000_EECD_CS; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(eeprom->delay_usec); + eecd &= ~E1000_EECD_CS; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(eeprom->delay_usec); + } } /****************************************************************************** - * Raises then lowers the EEPROM's clock pin + * Terminates a command by inverting the EEPROM's chip select pin * * hw - Struct containing variables accessed by shared code *****************************************************************************/ static void -e1000_clock_eeprom(struct e1000_hw *hw) +e1000_release_eeprom(struct e1000_hw *hw) { uint32_t eecd; + DEBUGFUNC("e1000_release_eeprom"); + eecd = E1000_READ_REG(hw, EECD); - /* Rising edge of clock */ - eecd |= E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); + if (hw->eeprom.type == e1000_eeprom_spi) { + eecd |= E1000_EECD_CS; /* Pull CS high */ + eecd &= ~E1000_EECD_SK; /* Lower SCK */ - /* Falling edge of clock */ - eecd &= ~E1000_EECD_SK; - E1000_WRITE_REG(hw, EECD, eecd); - E1000_WRITE_FLUSH(hw); - udelay(50); + E1000_WRITE_REG(hw, EECD, eecd); + + udelay(hw->eeprom.delay_usec); + } else if(hw->eeprom.type == e1000_eeprom_microwire) { + /* cleanup eeprom */ + + /* CS on Microwire is active-high */ + eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); + + E1000_WRITE_REG(hw, EECD, eecd); + + /* Rising edge of clock */ + eecd |= E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(hw->eeprom.delay_usec); + + /* Falling edge of clock */ + eecd &= ~E1000_EECD_SK; + E1000_WRITE_REG(hw, EECD, eecd); + E1000_WRITE_FLUSH(hw); + udelay(hw->eeprom.delay_usec); + } + + /* Stop requesting EEPROM access */ + if(hw->mac_type > e1000_82544) { + eecd &= ~E1000_EECD_REQ; + E1000_WRITE_REG(hw, EECD, eecd); + } } /****************************************************************************** - * Terminates a command by lowering the EEPROM's chip select pin + * Reads a 16 bit word from the EEPROM. * * hw - Struct containing variables accessed by shared code *****************************************************************************/ -static void -e1000_cleanup_eeprom(struct e1000_hw *hw) +int32_t +e1000_spi_eeprom_ready(struct e1000_hw *hw) { - uint32_t eecd; + uint16_t retry_count = 0; + uint8_t spi_stat_reg; - eecd = E1000_READ_REG(hw, EECD); + DEBUGFUNC("e1000_spi_eeprom_ready"); - eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); + /* Read "Status Register" repeatedly until the LSB is cleared. The + * EEPROM will signal that the command has been completed by clearing + * bit 0 of the internal status register. If it's not cleared within + * 5 milliseconds, then error out. + */ + retry_count = 0; + do { + e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI, + hw->eeprom.opcode_bits); + spi_stat_reg = (uint8_t)e1000_shift_in_ee_bits(hw, 8); + if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI)) + break; - E1000_WRITE_REG(hw, EECD, eecd); + udelay(5); + retry_count += 5; + + } while(retry_count < EEPROM_MAX_RETRY_SPI); - e1000_clock_eeprom(hw); + /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and + * only 0-5mSec on 5V devices) + */ + if(retry_count >= EEPROM_MAX_RETRY_SPI) { + DEBUGOUT("SPI EEPROM Status error\n"); + return -E1000_ERR_EEPROM; + } + + return E1000_SUCCESS; } /****************************************************************************** @@ -2477,71 +3030,76 @@ e1000_cleanup_eeprom(struct e1000_hw *hw) * * hw - Struct containing variables accessed by shared code * offset - offset of word in the EEPROM to read - * data - word read from the EEPROM + * data - word read from the EEPROM + * words - number of words to read *****************************************************************************/ int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t offset, + uint16_t words, uint16_t *data) { - uint32_t eecd; + struct e1000_eeprom_info *eeprom = &hw->eeprom; uint32_t i = 0; - boolean_t large_eeprom = FALSE; DEBUGFUNC("e1000_read_eeprom"); - /* Request EEPROM Access */ - if(hw->mac_type > e1000_82544) { - eecd = E1000_READ_REG(hw, EECD); - if(eecd & E1000_EECD_SIZE) large_eeprom = TRUE; - eecd |= E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - eecd = E1000_READ_REG(hw, EECD); - while((!(eecd & E1000_EECD_GNT)) && (i < 100)) { - i++; - udelay(5); - eecd = E1000_READ_REG(hw, EECD); - } - if(!(eecd & E1000_EECD_GNT)) { - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - DEBUGOUT("Could not acquire EEPROM grant\n"); - return -E1000_ERR_EEPROM; - } + /* A check for invalid values: offset too large, too many words, and not + * enough words. + */ + if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) || + (words == 0)) { + DEBUGOUT("\"words\" parameter out of bounds\n"); + return -E1000_ERR_EEPROM; } - /* Prepare the EEPROM for reading */ - e1000_setup_eeprom(hw); + /* Prepare the EEPROM for reading */ + if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) + return -E1000_ERR_EEPROM; - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE, 3); - if(large_eeprom) { - /* If we have a 256 word EEPROM, there are 8 address bits */ - e1000_shift_out_ee_bits(hw, offset, 8); - } else { - /* If we have a 64 word EEPROM, there are 6 address bits */ - e1000_shift_out_ee_bits(hw, offset, 6); - } + if(eeprom->type == e1000_eeprom_spi) { + uint8_t read_opcode = EEPROM_READ_OPCODE_SPI; - /* Read the data */ - *data = e1000_shift_in_ee_bits(hw); + if(e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM; - /* End this read operation */ - e1000_standby_eeprom(hw); + e1000_standby_eeprom(hw); - /* Stop requesting EEPROM access */ - if(hw->mac_type > e1000_82544) { - eecd = E1000_READ_REG(hw, EECD); - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); + /* Some SPI eeproms use the 8th address bit embedded in the opcode */ + if((eeprom->address_bits == 8) && (offset >= 128)) + read_opcode |= EEPROM_A8_OPCODE_SPI; + + /* Send the READ command (opcode + addr) */ + e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits); + e1000_shift_out_ee_bits(hw, (uint16_t)(offset*2), eeprom->address_bits); + } + else if(eeprom->type == e1000_eeprom_microwire) { + /* Send the READ command (opcode + addr) */ + e1000_shift_out_ee_bits(hw, EEPROM_READ_OPCODE_MICROWIRE, + eeprom->opcode_bits); + e1000_shift_out_ee_bits(hw, offset, eeprom->address_bits); } + /* Read the data. The address of the eeprom internally increments with + * each word (microwire) or byte (spi) being read, saving on the overhead + * of eeprom setup and tear-down. The address counter will roll over if + * reading beyond the size of the eeprom, thus allowing the entire memory + * to be read starting from any offset. */ + for (i = 0; i < words; i++) { + uint16_t word_in = e1000_shift_in_ee_bits(hw, 16); + if (eeprom->type == e1000_eeprom_spi) + word_in = (word_in >> 8) | (word_in << 8); + data[i] = word_in; + } + + /* End this read operation */ + e1000_release_eeprom(hw); + return 0; } /****************************************************************************** * Verifies that the EEPROM has a valid checksum - * + * * hw - Struct containing variables accessed by shared code * * Reads the first 64 16 bit words of the EEPROM and sums the values read. @@ -2557,7 +3115,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw) DEBUGFUNC("e1000_validate_eeprom_checksum"); for(i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if(e1000_read_eeprom(hw, i, &eeprom_data) < 0) { + if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -2589,14 +3147,14 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw) DEBUGFUNC("e1000_update_eeprom_checksum"); for(i = 0; i < EEPROM_CHECKSUM_REG; i++) { - if(e1000_read_eeprom(hw, i, &eeprom_data) < 0) { + if(e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } checksum += eeprom_data; } checksum = (uint16_t) EEPROM_SUM - checksum; - if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, checksum) < 0) { + if(e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) { DEBUGOUT("EEPROM Write Error\n"); return -E1000_ERR_EEPROM; } @@ -2604,118 +3162,201 @@ e1000_update_eeprom_checksum(struct e1000_hw *hw) } /****************************************************************************** - * Writes a 16 bit word to a given offset in the EEPROM. + * Parent function for writing words to the different EEPROM types. * * hw - Struct containing variables accessed by shared code * offset - offset within the EEPROM to be written to - * data - 16 bit word to be writen to the EEPROM + * words - number of words to write + * data - 16 bit word to be written to the EEPROM * - * If e1000_update_eeprom_checksum is not called after this function, the + * If e1000_update_eeprom_checksum is not called after this function, the * EEPROM will most likely contain an invalid checksum. *****************************************************************************/ int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t offset, - uint16_t data) + uint16_t words, + uint16_t *data) { - uint32_t eecd; - uint32_t i = 0; + struct e1000_eeprom_info *eeprom = &hw->eeprom; int32_t status = 0; - boolean_t large_eeprom = FALSE; DEBUGFUNC("e1000_write_eeprom"); - /* Request EEPROM Access */ - if(hw->mac_type > e1000_82544) { - eecd = E1000_READ_REG(hw, EECD); - if(eecd & E1000_EECD_SIZE) large_eeprom = TRUE; - eecd |= E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - eecd = E1000_READ_REG(hw, EECD); - while((!(eecd & E1000_EECD_GNT)) && (i < 100)) { - i++; - udelay(5); - eecd = E1000_READ_REG(hw, EECD); - } - if(!(eecd & E1000_EECD_GNT)) { - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); - DEBUGOUT("Could not acquire EEPROM grant\n"); - return -E1000_ERR_EEPROM; - } + /* A check for invalid values: offset too large, too many words, and not + * enough words. + */ + if((offset > eeprom->word_size) || (words > eeprom->word_size - offset) || + (words == 0)) { + DEBUGOUT("\"words\" parameter out of bounds\n"); + return -E1000_ERR_EEPROM; } /* Prepare the EEPROM for writing */ - e1000_setup_eeprom(hw); + if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) + return -E1000_ERR_EEPROM; - /* Send the 9-bit (or 11-bit on large EEPROM) EWEN (write enable) command - * to the EEPROM (5-bit opcode plus 4/6-bit dummy). This puts the EEPROM - * into write/erase mode. - */ - e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE, 5); - if(large_eeprom) - e1000_shift_out_ee_bits(hw, 0, 6); + if(eeprom->type == e1000_eeprom_microwire) + status = e1000_write_eeprom_microwire(hw, offset, words, data); else - e1000_shift_out_ee_bits(hw, 0, 4); + status = e1000_write_eeprom_spi(hw, offset, words, data); - /* Prepare the EEPROM */ - e1000_standby_eeprom(hw); + /* Done with writing */ + e1000_release_eeprom(hw); - /* Send the Write command (3-bit opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE, 3); - if(large_eeprom) - /* If we have a 256 word EEPROM, there are 8 address bits */ - e1000_shift_out_ee_bits(hw, offset, 8); - else - /* If we have a 64 word EEPROM, there are 6 address bits */ - e1000_shift_out_ee_bits(hw, offset, 6); + return status; +} + +/****************************************************************************** + * Writes a 16 bit word to a given offset in an SPI EEPROM. + * + * hw - Struct containing variables accessed by shared code + * offset - offset within the EEPROM to be written to + * words - number of words to write + * data - pointer to array of 8 bit words to be written to the EEPROM + * + *****************************************************************************/ +int32_t +e1000_write_eeprom_spi(struct e1000_hw *hw, + uint16_t offset, + uint16_t words, + uint16_t *data) +{ + struct e1000_eeprom_info *eeprom = &hw->eeprom; + uint16_t widx = 0; - /* Send the data */ - e1000_shift_out_ee_bits(hw, data, 16); + DEBUGFUNC("e1000_write_eeprom_spi"); - /* Toggle the CS line. This in effect tells to EEPROM to actually execute - * the command in question. - */ - e1000_standby_eeprom(hw); + while (widx < words) { + uint8_t write_opcode = EEPROM_WRITE_OPCODE_SPI; - /* Now read DO repeatedly until is high (equal to '1'). The EEEPROM will - * signal that the command has been completed by raising the DO signal. - * If DO does not go high in 10 milliseconds, then error out. - */ - for(i = 0; i < 200; i++) { - eecd = E1000_READ_REG(hw, EECD); - if(eecd & E1000_EECD_DO) break; - udelay(50); - } - if(i == 200) { - DEBUGOUT("EEPROM Write did not complete\n"); - status = -E1000_ERR_EEPROM; + if(e1000_spi_eeprom_ready(hw)) return -E1000_ERR_EEPROM; + + e1000_standby_eeprom(hw); + + /* Send the WRITE ENABLE command (8 bit opcode ) */ + e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI, + eeprom->opcode_bits); + + e1000_standby_eeprom(hw); + + /* Some SPI eeproms use the 8th address bit embedded in the opcode */ + if((eeprom->address_bits == 8) && (offset >= 128)) + write_opcode |= EEPROM_A8_OPCODE_SPI; + + /* Send the Write command (8-bit opcode + addr) */ + e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits); + + e1000_shift_out_ee_bits(hw, (uint16_t)((offset + widx)*2), + eeprom->address_bits); + + /* Send the data */ + + /* Loop to allow for up to whole page write (32 bytes) of eeprom */ + while (widx < words) { + uint16_t word_out = data[widx]; + word_out = (word_out >> 8) | (word_out << 8); + e1000_shift_out_ee_bits(hw, word_out, 16); + widx++; + + /* Some larger eeprom sizes are capable of a 32-byte PAGE WRITE + * operation, while the smaller eeproms are capable of an 8-byte + * PAGE WRITE operation. Break the inner loop to pass new address + */ + if((((offset + widx)*2) % eeprom->page_size) == 0) { + e1000_standby_eeprom(hw); + break; + } + } } - /* Recover from write */ - e1000_standby_eeprom(hw); + return E1000_SUCCESS; +} + +/****************************************************************************** + * Writes a 16 bit word to a given offset in a Microwire EEPROM. + * + * hw - Struct containing variables accessed by shared code + * offset - offset within the EEPROM to be written to + * words - number of words to write + * data - pointer to array of 16 bit words to be written to the EEPROM + * + *****************************************************************************/ +int32_t +e1000_write_eeprom_microwire(struct e1000_hw *hw, + uint16_t offset, + uint16_t words, + uint16_t *data) +{ + struct e1000_eeprom_info *eeprom = &hw->eeprom; + uint32_t eecd; + uint16_t words_written = 0; + uint16_t i = 0; - /* Send the 9-bit (or 11-bit on large EEPROM) EWDS (write disable) command - * to the EEPROM (5-bit opcode plus 4/6-bit dummy). This takes the EEPROM - * out of write/erase mode. + DEBUGFUNC("e1000_write_eeprom_microwire"); + + /* Send the write enable command to the EEPROM (3-bit opcode plus + * 6/8-bit dummy address beginning with 11). It's less work to include + * the 11 of the dummy address as part of the opcode than it is to shift + * it over the correct number of bits for the address. This puts the + * EEPROM into write/erase mode. */ - e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE, 5); - if(large_eeprom) - e1000_shift_out_ee_bits(hw, 0, 6); - else - e1000_shift_out_ee_bits(hw, 0, 4); + e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE, + (uint16_t)(eeprom->opcode_bits + 2)); - /* Done with writing */ - e1000_cleanup_eeprom(hw); + e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2)); - /* Stop requesting EEPROM access */ - if(hw->mac_type > e1000_82544) { - eecd = E1000_READ_REG(hw, EECD); - eecd &= ~E1000_EECD_REQ; - E1000_WRITE_REG(hw, EECD, eecd); + /* Prepare the EEPROM */ + e1000_standby_eeprom(hw); + + while (words_written < words) { + /* Send the Write command (3-bit opcode + addr) */ + e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE, + eeprom->opcode_bits); + + e1000_shift_out_ee_bits(hw, (uint16_t)(offset + words_written), + eeprom->address_bits); + + /* Send the data */ + e1000_shift_out_ee_bits(hw, data[words_written], 16); + + /* Toggle the CS line. This in effect tells the EEPROM to execute + * the previous command. + */ + e1000_standby_eeprom(hw); + + /* Read DO repeatedly until it is high (equal to '1'). The EEPROM will + * signal that the command has been completed by raising the DO signal. + * If DO does not go high in 10 milliseconds, then error out. + */ + for(i = 0; i < 200; i++) { + eecd = E1000_READ_REG(hw, EECD); + if(eecd & E1000_EECD_DO) break; + udelay(50); + } + if(i == 200) { + DEBUGOUT("EEPROM Write did not complete\n"); + return -E1000_ERR_EEPROM; + } + + /* Recover from write */ + e1000_standby_eeprom(hw); + + words_written++; } - return status; + /* Send the write disable command to the EEPROM (3-bit opcode plus + * 6/8-bit dummy address beginning with 10). It's less work to include + * the 10 of the dummy address as part of the opcode than it is to shift + * it over the correct number of bits for the address. This takes the + * EEPROM out of write/erase mode. + */ + e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE, + (uint16_t)(eeprom->opcode_bits + 2)); + + e1000_shift_out_ee_bits(hw, 0, (uint16_t)(eeprom->address_bits - 2)); + + return 0; } /****************************************************************************** @@ -2734,7 +3375,7 @@ e1000_read_part_num(struct e1000_hw *hw, DEBUGFUNC("e1000_read_part_num"); /* Get word 0 from EEPROM */ - if(e1000_read_eeprom(hw, offset, &eeprom_data) < 0) { + if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -2742,7 +3383,7 @@ e1000_read_part_num(struct e1000_hw *hw, *part_num = (uint32_t) (eeprom_data << 16); /* Get word 1 from EEPROM */ - if(e1000_read_eeprom(hw, ++offset, &eeprom_data) < 0) { + if(e1000_read_eeprom(hw, ++offset, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -2768,7 +3409,7 @@ e1000_read_mac_addr(struct e1000_hw * hw) for(i = 0; i < NODE_ADDRESS_SIZE; i += 2) { offset = i >> 1; - if(e1000_read_eeprom(hw, offset, &eeprom_data) < 0) { + if(e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } @@ -3055,24 +3696,24 @@ e1000_id_led_init(struct e1000_hw * hw) const uint32_t ledctl_off = E1000_LEDCTL_MODE_LED_OFF; uint16_t eeprom_data, i, temp; const uint16_t led_mask = 0x0F; - + DEBUGFUNC("e1000_id_led_init"); - + if(hw->mac_type < e1000_82540) { /* Nothing to do */ return 0; } - + ledctl = E1000_READ_REG(hw, LEDCTL); hw->ledctl_default = ledctl; hw->ledctl_mode1 = hw->ledctl_default; hw->ledctl_mode2 = hw->ledctl_default; - - if(e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, &eeprom_data) < 0) { + + if(e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) { DEBUGOUT("EEPROM Read Error\n"); return -E1000_ERR_EEPROM; } - if((eeprom_data== ID_LED_RESERVED_0000) || + if((eeprom_data== ID_LED_RESERVED_0000) || (eeprom_data == ID_LED_RESERVED_FFFF)) eeprom_data = ID_LED_DEFAULT; for(i = 0; i < 4; i++) { temp = (eeprom_data >> (i << 2)) & led_mask; @@ -3155,6 +3796,9 @@ e1000_setup_led(struct e1000_hw *hw) case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82541EI: + case E1000_DEV_ID_82541EP: + case E1000_DEV_ID_82547EI: E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); break; default: @@ -3193,6 +3837,9 @@ e1000_cleanup_led(struct e1000_hw *hw) case E1000_DEV_ID_82545EM_FIBER: case E1000_DEV_ID_82546EB_COPPER: case E1000_DEV_ID_82546EB_FIBER: + case E1000_DEV_ID_82541EI: + case E1000_DEV_ID_82541EP: + case E1000_DEV_ID_82547EI: /* Restore LEDCTL settings */ E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_default); break; @@ -3244,6 +3891,9 @@ e1000_led_on(struct e1000_hw *hw) case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82541EI: + case E1000_DEV_ID_82541EP: + case E1000_DEV_ID_82547EI: E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode2); break; default: @@ -3294,6 +3944,9 @@ e1000_led_off(struct e1000_hw *hw) case E1000_DEV_ID_82540EM_LOM: case E1000_DEV_ID_82545EM_COPPER: case E1000_DEV_ID_82546EB_COPPER: + case E1000_DEV_ID_82541EI: + case E1000_DEV_ID_82541EP: + case E1000_DEV_ID_82547EI: E1000_WRITE_REG(hw, LEDCTL, hw->ledctl_mode1); break; default: @@ -3608,3 +4261,221 @@ e1000_write_reg_io(struct e1000_hw *hw, e1000_io_write(hw, io_data, value); } + +/****************************************************************************** + * Estimates the cable length. + * + * hw - Struct containing variables accessed by shared code + * min_length - The estimated minimum length + * max_length - The estimated maximum length + * + * returns: E1000_SUCCESS / -E1000_ERR_XXX + * + * This function always returns a ranged length (minimum & maximum). + * So for M88 phy's, this function interprets the one value returned from the + * register to the minimum and maximum range. + * For IGP phy's, the function calculates the range by the AGC registers. + *****************************************************************************/ +int32_t +e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, + uint16_t *max_length) +{ + uint16_t agc_value = 0; + uint16_t cur_agc, min_agc = IGP01E1000_AGC_LENGTH_TABLE_SIZE; + uint16_t i, phy_data; + + DEBUGFUNC("e1000_get_cable_length"); + + *min_length = *max_length = 0; + + /* Use old method for Phy older than IGP */ + if(hw->phy_type == e1000_phy_m88) { + if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) + return -E1000_ERR_PHY; + + /* Convert the enum value to ranged values */ + switch((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> + M88E1000_PSSR_CABLE_LENGTH_SHIFT) { + case e1000_cable_length_50: + *min_length = 0; + *max_length = e1000_igp_cable_length_50; + break; + case e1000_cable_length_50_80: + *min_length = e1000_igp_cable_length_50; + *max_length = e1000_igp_cable_length_80; + break; + case e1000_cable_length_80_110: + *min_length = e1000_igp_cable_length_80; + *max_length = e1000_igp_cable_length_110; + break; + case e1000_cable_length_110_140: + *min_length = e1000_igp_cable_length_110; + *max_length = e1000_igp_cable_length_140; + break; + case e1000_cable_length_140: + *min_length = e1000_igp_cable_length_140; + *max_length = e1000_igp_cable_length_170; + break; + default: + return -E1000_ERR_PHY; + break; + } + } else if(hw->phy_type == e1000_phy_igp) { /* For IGP PHY */ + uint16_t agc_reg_array[IGP01E1000_PHY_AGC_NUM] = {IGP01E1000_PHY_AGC_A, + IGP01E1000_PHY_AGC_B, + IGP01E1000_PHY_AGC_C, + IGP01E1000_PHY_AGC_D}; + /* Read the AGC registers for all channels */ + for(i = 0; i < IGP01E1000_PHY_AGC_NUM; i++) { + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, + agc_reg_array[i]) != E1000_SUCCESS) + return -E1000_ERR_PHY; + if(e1000_read_phy_reg(hw, agc_reg_array[i] & + IGP01E1000_PHY_PAGE_SELECT, &phy_data) != + E1000_SUCCESS) + return -E1000_ERR_PHY; + + cur_agc = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; + + /* Array bound check. */ + if((cur_agc >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) || + (cur_agc == 0)) + return -E1000_ERR_PHY; + + agc_value += cur_agc; + + /* Update minimal AGC value. */ + if(min_agc > cur_agc) + min_agc = cur_agc; + } + + /* Return to page 0 */ + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) != + E1000_SUCCESS) + return -E1000_ERR_PHY; + + /* Remove the minimal AGC result for length < 50m */ + if(agc_value < IGP01E1000_PHY_AGC_NUM * e1000_igp_cable_length_50) { + agc_value -= min_agc; + + /* Get the average length of the remaining 3 channels */ + agc_value /= (IGP01E1000_PHY_AGC_NUM - 1); + } else { + /* Get the average length of all the 4 channels. */ + agc_value /= IGP01E1000_PHY_AGC_NUM; + } + + /* Set the range of the calculated length. */ + *min_length = ((e1000_igp_cable_length_table[agc_value] - + IGP01E1000_AGC_RANGE) > 0) ? + (e1000_igp_cable_length_table[agc_value] - + IGP01E1000_AGC_RANGE) : 0; + *max_length = e1000_igp_cable_length_table[agc_value] + + IGP01E1000_AGC_RANGE; + } + + return E1000_SUCCESS; +} + +/****************************************************************************** + * Check the cable polarity + * + * hw - Struct containing variables accessed by shared code + * polarity - output parameter : 0 - Polarity is not reversed + * 1 - Polarity is reversed. + * + * returns: E1000_SUCCESS / -E1000_ERR_XXX + * + * For phy's older then IGP, this function simply reads the polarity bit in the + * Phy Status register. For IGP phy's, this bit is valid only if link speed is + * 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will + * return 0. If the link speed is 1000 Mbps the polarity status is in the + * IGP01E1000_PHY_PCS_INIT_REG. + *****************************************************************************/ +int32_t +e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity) +{ + uint16_t phy_data; + + DEBUGFUNC("e1000_check_polarity"); + + if(hw->phy_type == e1000_phy_m88) { + /* return the Polarity bit in the Status register. */ + if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) + return -E1000_ERR_PHY; + *polarity = (phy_data & M88E1000_PSSR_REV_POLARITY) >> + M88E1000_PSSR_REV_POLARITY_SHIFT; + } else if(hw->phy_type == e1000_phy_igp) { + /* Read the Status register to check the speed */ + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) + return -E1000_ERR_PHY; + + /* If speed is 1000 Mbps, must read the IGP01E1000_PHY_PCS_INIT_REG to + * find the polarity status */ + if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) { + + /* Read the GIG initialization PCS register (0x00B4) */ + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, + IGP01E1000_PHY_PCS_INIT_REG) < 0) + return -E1000_ERR_PHY; + + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG & + IGP01E1000_PHY_PAGE_SELECT, &phy_data) < 0) + return -E1000_ERR_PHY; + + /* Return to page 0 */ + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0) != + E1000_SUCCESS) + return -E1000_ERR_PHY; + + /* Check the polarity bits */ + *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? 1 : 0; + } else { + /* For 10 Mbps, read the polarity bit in the status register. (for + * 100 Mbps this bit is always 0) */ + *polarity = phy_data & IGP01E1000_PSSR_POLARITY_REVERSED; + } + } + return E1000_SUCCESS; +} + +/****************************************************************************** + * Check if Downshift occured + * + * hw - Struct containing variables accessed by shared code + * downshift - output parameter : 0 - No Downshift ocured. + * 1 - Downshift ocured. + * + * returns: E1000_SUCCESS / -E1000_ERR_XXX + * + * For phy's older then IGP, this function reads the Downshift bit in the Phy + * Specific Status register. For IGP phy's, it reads the Downgrade bit in the + * Link Health register. In IGP this bit is latched high, so the driver must + * read it immediately after link is established. + *****************************************************************************/ +int32_t +e1000_check_downshift(struct e1000_hw *hw) +{ + uint16_t phy_data; + + DEBUGFUNC("e1000_check_downshift"); + + if(hw->phy_type == e1000_phy_igp) { + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + hw->speed_downgraded = (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; + } + else if(hw->phy_type == e1000_phy_m88) { + if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> + M88E1000_PSSR_DOWNSHIFT_SHIFT; + } + return E1000_SUCCESS; +} + diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index d2d5e3773a32..5e1fbab33047 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -50,9 +50,18 @@ typedef enum { e1000_82540, e1000_82545, e1000_82546, + e1000_82541, + e1000_82547, e1000_num_macs } e1000_mac_type; +typedef enum { + e1000_eeprom_uninitialized = 0, + e1000_eeprom_spi, + e1000_eeprom_microwire, + e1000_num_eeprom_types +} e1000_eeprom_type; + /* Media Types */ typedef enum { e1000_media_type_copper = 0, @@ -110,6 +119,27 @@ typedef enum { e1000_cable_length_undefined = 0xFF } e1000_cable_length; +typedef enum { + e1000_igp_cable_length_10 = 10, + e1000_igp_cable_length_20 = 20, + e1000_igp_cable_length_30 = 30, + e1000_igp_cable_length_40 = 40, + e1000_igp_cable_length_50 = 50, + e1000_igp_cable_length_60 = 60, + e1000_igp_cable_length_70 = 70, + e1000_igp_cable_length_80 = 80, + e1000_igp_cable_length_90 = 90, + e1000_igp_cable_length_100 = 100, + e1000_igp_cable_length_110 = 110, + e1000_igp_cable_length_120 = 120, + e1000_igp_cable_length_130 = 130, + e1000_igp_cable_length_140 = 140, + e1000_igp_cable_length_150 = 150, + e1000_igp_cable_length_160 = 160, + e1000_igp_cable_length_170 = 170, + e1000_igp_cable_length_180 = 180 +} e1000_igp_cable_length; + typedef enum { e1000_10bt_ext_dist_enable_normal = 0, e1000_10bt_ext_dist_enable_lower, @@ -122,6 +152,12 @@ typedef enum { e1000_rev_polarity_undefined = 0xFF } e1000_rev_polarity; +typedef enum { + e1000_downshift_normal = 0, + e1000_downshift_activated, + e1000_downshift_undefined = 0xFF +} e1000_downshift; + typedef enum { e1000_polarity_reversal_enabled = 0, e1000_polarity_reversal_disabled, @@ -142,10 +178,17 @@ typedef enum { e1000_1000t_rx_status_undefined = 0xFF } e1000_1000t_rx_status; +typedef enum { + e1000_phy_m88 = 0, + e1000_phy_igp, + e1000_phy_undefined = 0xFF +} e1000_phy_type; + struct e1000_phy_info { e1000_cable_length cable_length; e1000_10bt_ext_dist_enable extended_10bt_distance; e1000_rev_polarity cable_polarity; + e1000_downshift downshift; e1000_polarity_reversal polarity_correction; e1000_auto_x_mode mdix_mode; e1000_1000t_rx_status local_rx; @@ -157,6 +200,15 @@ struct e1000_phy_stats { uint32_t receive_errors; }; +struct e1000_eeprom_info { + e1000_eeprom_type type; + uint16_t word_size; + uint16_t opcode_bits; + uint16_t address_bits; + uint16_t delay_usec; + uint16_t page_size; +}; + /* Error Codes */ @@ -166,6 +218,7 @@ struct e1000_phy_stats { #define E1000_ERR_CONFIG 3 #define E1000_ERR_PARAM 4 #define E1000_ERR_MAC_TYPE 5 +#define E1000_ERR_PHY_TYPE 6 /* Function prototypes */ /* Initialization */ @@ -189,13 +242,19 @@ void e1000_phy_hw_reset(struct e1000_hw *hw); int32_t e1000_phy_reset(struct e1000_hw *hw); int32_t e1000_detect_gig_phy(struct e1000_hw *hw); int32_t e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); +int32_t e1000_phy_m88_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); +int32_t e1000_phy_igp_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); +int32_t e1000_get_cable_length(struct e1000_hw *hw, uint16_t *min_length, uint16_t *max_length); +int32_t e1000_check_polarity(struct e1000_hw *hw, uint16_t *polarity); +int32_t e1000_check_downshift(struct e1000_hw *hw); int32_t e1000_validate_mdi_setting(struct e1000_hw *hw); /* EEPROM Functions */ -int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t *data); +void e1000_init_eeprom_params(struct e1000_hw *hw); +int32_t e1000_read_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); int32_t e1000_validate_eeprom_checksum(struct e1000_hw *hw); int32_t e1000_update_eeprom_checksum(struct e1000_hw *hw); -int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t data); +int32_t e1000_write_eeprom(struct e1000_hw *hw, uint16_t reg, uint16_t words, uint16_t *data); int32_t e1000_read_part_num(struct e1000_hw *hw, uint32_t * part_num); int32_t e1000_read_mac_addr(struct e1000_hw * hw); @@ -253,7 +312,10 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); #define E1000_DEV_ID_82545EM_FIBER 0x1011 #define E1000_DEV_ID_82546EB_COPPER 0x1010 #define E1000_DEV_ID_82546EB_FIBER 0x1012 -#define NUM_DEV_IDS 16 +#define E1000_DEV_ID_82541EI 0x1013 +#define E1000_DEV_ID_82541EP 0x1018 +#define E1000_DEV_ID_82547EI 0x1019 +#define NUM_DEV_IDS 19 #define NODE_ADDRESS_SIZE 6 #define ETH_LENGTH_OF_ADDRESS 6 @@ -322,9 +384,9 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); /* The number of high/low register pairs in the RAR. The RAR (Receive Address * Registers) holds the directed and multicast addresses that we monitor. We * reserve one of these spots for our directed address, allowing us room for - * E1000_RAR_ENTRIES - 1 multicast addresses. + * E1000_RAR_ENTRIES - 1 multicast addresses. */ -#define E1000_RAR_ENTRIES 16 +#define E1000_RAR_ENTRIES 15 #define MIN_NUMBER_OF_DESCRIPTORS 8 #define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 @@ -537,6 +599,7 @@ struct e1000_ffvt_entry { #define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ #define E1000_EERD 0x00014 /* EEPROM Read - RW */ #define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ +#define E1000_FLA 0x0001C /* Flash Access Register - RW */ #define E1000_MDIC 0x00020 /* MDI Control - RW */ #define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ #define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ @@ -569,6 +632,11 @@ struct e1000_ffvt_entry { #define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ #define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ #define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ +#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */ +#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */ +#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */ +#define E1000_TDFTS 0x03428 /* TX Data FIFO Tail Saved - RW */ +#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */ #define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */ #define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */ #define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */ @@ -664,6 +732,7 @@ struct e1000_ffvt_entry { #define E1000_82542_EECD E1000_EECD #define E1000_82542_EERD E1000_EERD #define E1000_82542_CTRL_EXT E1000_CTRL_EXT +#define E1000_82542_FLA E1000_FLA #define E1000_82542_MDIC E1000_MDIC #define E1000_82542_FCAL E1000_FCAL #define E1000_82542_FCAH E1000_FCAH @@ -705,6 +774,9 @@ struct e1000_ffvt_entry { #define E1000_82542_RADV E1000_RADV #define E1000_82542_RSRPD E1000_RSRPD #define E1000_82542_TXDMAC E1000_TXDMAC +#define E1000_82542_TDFHS E1000_TDFHS +#define E1000_82542_TDFTS E1000_TDFTS +#define E1000_82542_TDFPC E1000_TDFPC #define E1000_82542_TXDCTL E1000_TXDCTL #define E1000_82542_TADV E1000_TADV #define E1000_82542_TSPMT E1000_TSPMT @@ -777,6 +849,8 @@ struct e1000_ffvt_entry { #define E1000_82542_WUPL E1000_WUPL #define E1000_82542_WUPM E1000_WUPM #define E1000_82542_FFLT E1000_FFLT +#define E1000_82542_TDFH 0x08010 +#define E1000_82542_TDFT 0x08018 #define E1000_82542_FFMT E1000_FFMT #define E1000_82542_FFVT E1000_FFVT @@ -846,12 +920,15 @@ struct e1000_hw_stats { struct e1000_hw { uint8_t *hw_addr; e1000_mac_type mac_type; + e1000_phy_type phy_type; + uint32_t phy_init_script; e1000_media_type media_type; void *back; e1000_fc_type fc; e1000_bus_speed bus_speed; e1000_bus_width bus_width; e1000_bus_type bus_type; + struct e1000_eeprom_info eeprom; uint32_t io_base; uint32_t phy_id; uint32_t phy_revision; @@ -891,6 +968,7 @@ struct e1000_hw { uint8_t mac_addr[NODE_ADDRESS_SIZE]; uint8_t perm_mac_addr[NODE_ADDRESS_SIZE]; boolean_t disable_polarity_correction; + boolean_t speed_downgraded; boolean_t get_link_status; boolean_t tbi_compatibility_en; boolean_t tbi_compatibility_on; @@ -967,14 +1045,20 @@ struct e1000_hw { #define E1000_EECD_CS 0x00000002 /* EEPROM Chip Select */ #define E1000_EECD_DI 0x00000004 /* EEPROM Data In */ #define E1000_EECD_DO 0x00000008 /* EEPROM Data Out */ -#define E1000_EECD_FWE_MASK 0x00000030 +#define E1000_EECD_FWE_MASK 0x00000030 #define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */ #define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */ #define E1000_EECD_FWE_SHIFT 4 -#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ #define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */ #define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */ #define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ +#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ +#define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type + * (0-small, 1-large) */ +#define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */ +#ifndef E1000_EEPROM_GRANT_ATTEMPTS +#define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ +#endif /* EEPROM Read */ #define E1000_EERD_START 0x00000001 /* Start Read */ @@ -984,8 +1068,15 @@ struct e1000_hw { #define E1000_EERD_DATA_SHIFT 16 #define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */ +/* SPI EEPROM Status Register */ +#define EEPROM_STATUS_RDY_SPI 0x01 +#define EEPROM_STATUS_WEN_SPI 0x02 +#define EEPROM_STATUS_BP0_SPI 0x04 +#define EEPROM_STATUS_BP1_SPI 0x08 +#define EEPROM_STATUS_WPEN_SPI 0x80 + /* Extended Device Control */ -#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ +#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ #define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ #define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN #define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */ @@ -1239,6 +1330,7 @@ struct e1000_hw { #define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ #define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ #define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ +#define E1000_WUC_SPM 0x80000000 /* Enable SPM */ /* Wake Up Filter Control */ #define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ @@ -1302,18 +1394,40 @@ struct e1000_hw { #define E1000_MDALIGN 4096 -/* EEPROM Commands */ -#define EEPROM_READ_OPCODE 0x6 /* EERPOM read opcode */ -#define EEPROM_WRITE_OPCODE 0x5 /* EERPOM write opcode */ -#define EEPROM_ERASE_OPCODE 0x7 /* EERPOM erase opcode */ -#define EEPROM_EWEN_OPCODE 0x13 /* EERPOM erase/write enable */ -#define EEPROM_EWDS_OPCODE 0x10 /* EERPOM erast/write disable */ +/* EEPROM Commands - Microwire */ +#define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */ +#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */ +#define EEPROM_ERASE_OPCODE_MICROWIRE 0x7 /* EEPROM erase opcode */ +#define EEPROM_EWEN_OPCODE_MICROWIRE 0x13 /* EEPROM erase/write enable */ +#define EEPROM_EWDS_OPCODE_MICROWIRE 0x10 /* EEPROM erast/write disable */ + +/* EEPROM Commands - SPI */ +#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ +#define EEPROM_READ_OPCODE_SPI 0x3 /* EEPROM read opcode */ +#define EEPROM_WRITE_OPCODE_SPI 0x2 /* EEPROM write opcode */ +#define EEPROM_A8_OPCODE_SPI 0x8 /* opcode bit-3 = address bit-8 */ +#define EEPROM_WREN_OPCODE_SPI 0x6 /* EEPROM set Write Enable latch */ +#define EEPROM_WRDI_OPCODE_SPI 0x4 /* EEPROM reset Write Enable latch */ +#define EEPROM_RDSR_OPCODE_SPI 0x5 /* EEPROM read Status register */ +#define EEPROM_WRSR_OPCODE_SPI 0x1 /* EEPROM write Status register */ + +/* EEPROM Size definitions */ +#define EEPROM_SIZE_16KB 0x1800 +#define EEPROM_SIZE_8KB 0x1400 +#define EEPROM_SIZE_4KB 0x1000 +#define EEPROM_SIZE_2KB 0x0C00 +#define EEPROM_SIZE_1KB 0x0800 +#define EEPROM_SIZE_512B 0x0400 +#define EEPROM_SIZE_128B 0x0000 +#define EEPROM_SIZE_MASK 0x1C00 + /* EEPROM Word Offsets */ #define EEPROM_COMPAT 0x0003 #define EEPROM_ID_LED_SETTINGS 0x0004 #define EEPROM_INIT_CONTROL1_REG 0x000A #define EEPROM_INIT_CONTROL2_REG 0x000F +#define EEPROM_CFG 0x0012 #define EEPROM_FLASH_VERSION 0x0032 #define EEPROM_CHECKSUM_REG 0x003F @@ -1334,9 +1448,10 @@ struct e1000_hw { #define ID_LED_OFF1_ON2 0x8 #define ID_LED_OFF1_OFF2 0x9 -/* Mask bits for fields in Word 0x03 of the EEPROM */ -#define EEPROM_COMPAT_SERVER 0x0400 -#define EEPROM_COMPAT_CLIENT 0x0200 +#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF +#define IGP_ACTIVITY_LED_ENABLE 0x0300 +#define IGP_LED3_MODE 0x07000000 + /* Mask bits for fields in Word 0x0a of the EEPROM */ #define EEPROM_WORD0A_ILOS 0x0010 @@ -1409,7 +1524,9 @@ struct e1000_hw { /* PBA constants */ #define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ +#define E1000_PBA_22K 0x0016 #define E1000_PBA_24K 0x0018 +#define E1000_PBA_30K 0x001E #define E1000_PBA_40K 0x0028 #define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ @@ -1547,6 +1664,29 @@ struct e1000_hw { #define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ #define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ +/* IGP01E1000 Specific Registers */ +#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */ +#define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */ +#define IGP01E1000_PHY_PORT_CTRL 0x12 /* PHY Specific Control Register */ +#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */ +#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */ +#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */ +#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */ + +/* IGP01E1000 AGC Registers - stores the cable length values*/ +#define IGP01E1000_PHY_AGC_A 0x1172 +#define IGP01E1000_PHY_AGC_B 0x1272 +#define IGP01E1000_PHY_AGC_C 0x1472 +#define IGP01E1000_PHY_AGC_D 0x1872 + +/* Number of AGC registers */ +#define IGP01E1000_PHY_AGC_NUM 4 + +/* IGP01E1000 PCS Initialization register - stores the polarity status when + * speed = 1000 Mbps. */ +#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 + + #define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ /* PHY Control Register */ @@ -1712,6 +1852,7 @@ struct e1000_hw { /* M88E1000 PHY Specific Status Register */ #define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ #define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ +#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ #define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ #define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M; * 3=110-140M;4=>140M */ @@ -1725,6 +1866,7 @@ struct e1000_hw { #define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ #define M88E1000_PSSR_REV_POLARITY_SHIFT 1 +#define M88E1000_PSSR_DOWNSHIFT_SHIFT 5 #define M88E1000_PSSR_MDIX_SHIFT 6 #define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 @@ -1753,10 +1895,93 @@ struct e1000_hw { #define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ #define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ + +/* IGP01E1000 Specific Port Config Register - R/W */ +#define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 +#define IGP01E1000_PSCFR_PRE_EN 0x0020 +#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 +#define IGP01E1000_PSCFR_DISABLE_TPLOOPBACK 0x0100 +#define IGP01E1000_PSCFR_DISABLE_JABBER 0x0400 +#define IGP01E1000_PSCFR_DISABLE_TRANSMIT 0x2000 + +/* IGP01E1000 Specific Port Status Register - R/O */ +#define IGP01E1000_PSSR_AUTONEG_FAILED 0x0001 /* RO LH SC */ +#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 +#define IGP01E1000_PSSR_CABLE_LENGTH 0x007C +#define IGP01E1000_PSSR_FULL_DUPLEX 0x0200 +#define IGP01E1000_PSSR_LINK_UP 0x0400 +#define IGP01E1000_PSSR_MDIX 0x0800 +#define IGP01E1000_PSSR_SPEED_MASK 0xC000 /* speed bits mask */ +#define IGP01E1000_PSSR_SPEED_10MBPS 0x4000 +#define IGP01E1000_PSSR_SPEED_100MBPS 0x8000 +#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 +#define IGP01E1000_PSSR_CABLE_LENGTH_SHIFT 0x0002 /* shift right 2 */ +#define IGP01E1000_PSSR_MDIX_SHIFT 0x000B /* shift right 11 */ + +/* IGP01E1000 Specific Port Control Register - R/W */ +#define IGP01E1000_PSCR_TP_LOOPBACK 0x0001 +#define IGP01E1000_PSCR_CORRECT_NC_SCMBLR 0x0200 +#define IGP01E1000_PSCR_TEN_CRS_SELECT 0x0400 +#define IGP01E1000_PSCR_FLIP_CHIP 0x0800 +#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 +#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0-MDI, 1-MDIX */ + +/* IGP01E1000 Specific Port Link Health Register */ +#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 +#define IGP01E1000_PLHR_GIG_SCRAMBLER_ERROR 0x4000 +#define IGP01E1000_PLHR_GIG_REM_RCVR_NOK 0x0800 /* LH */ +#define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW 0x0400 /* LH */ +#define IGP01E1000_PLHR_DATA_ERR_1 0x0200 /* LH */ +#define IGP01E1000_PLHR_DATA_ERR_0 0x0100 +#define IGP01E1000_PLHR_AUTONEG_FAULT 0x0010 +#define IGP01E1000_PLHR_AUTONEG_ACTIVE 0x0008 +#define IGP01E1000_PLHR_VALID_CHANNEL_D 0x0004 +#define IGP01E1000_PLHR_VALID_CHANNEL_C 0x0002 +#define IGP01E1000_PLHR_VALID_CHANNEL_B 0x0001 +#define IGP01E1000_PLHR_VALID_CHANNEL_A 0x0000 + +/* IGP01E1000 Channel Quality Register */ +#define IGP01E1000_MSE_CHANNEL_D 0x000F +#define IGP01E1000_MSE_CHANNEL_C 0x00F0 +#define IGP01E1000_MSE_CHANNEL_B 0x0F00 +#define IGP01E1000_MSE_CHANNEL_A 0xF000 + +/* IGP01E1000 AGC Registers */ + +#define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */ + +/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */ +#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128 + +/* The precision of the length is +/- 10 meters */ +#define IGP01E1000_AGC_RANGE 10 + +/* IGP cable length table */ +static const +uint16_t e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = + { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, + 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120}; + +/* IGP01E1000 PCS Initialization register */ +/* bits 3:6 in the PCS registers stores the channels polarity */ +#define IGP01E1000_PHY_POLARITY_MASK 0x0078 + +/* IGP01E1000 GMII FIFO Register */ +#define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed + * on Link-Up */ +#define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */ + /* Bit definitions for valid PHY IDs. */ #define M88E1000_E_PHY_ID 0x01410C50 #define M88E1000_I_PHY_ID 0x01410C30 #define M88E1011_I_PHY_ID 0x01410C20 +#define IGP01E1000_I_PHY_ID 0x02A80380 #define M88E1000_12_PHY_ID M88E1000_E_PHY_ID #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID #define M88E1011_I_REV_4 0x04 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 7c39f533479d..2590e35a57d4 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -106,6 +106,8 @@ static struct pci_device_id e1000_pci_tbl[] __devinitdata = { {0x8086, 0x1016, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x1017, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {0x8086, 0x101E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1013, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0x8086, 0x1019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, /* required last entry */ {0,} }; @@ -144,6 +146,7 @@ static void e1000_free_rx_resources(struct e1000_adapter *adapter); static void e1000_set_multi(struct net_device *netdev); static void e1000_update_phy_info(unsigned long data); static void e1000_watchdog(unsigned long data); +static void e1000_82547_tx_fifo_stall(unsigned long data); static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev); static struct net_device_stats * e1000_get_stats(struct net_device *netdev); static int e1000_change_mtu(struct net_device *netdev, int new_mtu); @@ -167,6 +170,9 @@ static inline void e1000_rx_checksum(struct e1000_adapter *adapter, struct sk_buff *skb); static void e1000_tx_timeout(struct net_device *dev); static void e1000_tx_timeout_task(struct net_device *dev); +static void e1000_smartspeed(struct e1000_adapter *adapter); +static inline int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, + struct sk_buff *skb); static void e1000_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); static void e1000_vlan_rx_add_vid(struct net_device *netdev, uint16_t vid); @@ -284,6 +290,7 @@ e1000_down(struct e1000_adapter *adapter) e1000_irq_disable(adapter); free_irq(netdev->irq, netdev); + del_timer_sync(&adapter->tx_fifo_stall_timer); del_timer_sync(&adapter->watchdog_timer); del_timer_sync(&adapter->phy_info_timer); adapter->link_speed = 0; @@ -299,14 +306,28 @@ e1000_down(struct e1000_adapter *adapter) void e1000_reset(struct e1000_adapter *adapter) { + uint32_t pba; /* Repartition Pba for greater than 9k mtu * To take effect CTRL.RST is required. */ - if(adapter->rx_buffer_len > E1000_RXBUFFER_8192) - E1000_WRITE_REG(&adapter->hw, PBA, E1000_JUMBO_PBA); - else - E1000_WRITE_REG(&adapter->hw, PBA, E1000_DEFAULT_PBA); + if(adapter->hw.mac_type < e1000_82547) { + if(adapter->rx_buffer_len > E1000_RXBUFFER_8192) + pba = E1000_PBA_40K; + else + pba = E1000_PBA_48K; + } else { + if(adapter->rx_buffer_len > E1000_RXBUFFER_8192) + pba = E1000_PBA_22K; + else + pba = E1000_PBA_30K; + adapter->tx_fifo_head = 0; + adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; + adapter->tx_fifo_size = + (E1000_PBA_40K - pba) << E1000_TX_FIFO_SIZE_SHIFT; + atomic_set(&adapter->tx_fifo_stall, 0); + } + E1000_WRITE_REG(&adapter->hw, PBA, pba); adapter->hw.fc = adapter->hw.original_fc; e1000_reset_hw(&adapter->hw); @@ -397,11 +418,11 @@ e1000_probe(struct pci_dev *pdev, netdev->change_mtu = &e1000_change_mtu; netdev->do_ioctl = &e1000_ioctl; netdev->tx_timeout = &e1000_tx_timeout; - netdev->watchdog_timeo = HZ; #ifdef CONFIG_E1000_NAPI netdev->poll = &e1000_poll; netdev->weight = 64; #endif + netdev->watchdog_timeo = 5 * HZ; netdev->vlan_rx_register = e1000_vlan_rx_register; netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid; @@ -421,17 +442,18 @@ e1000_probe(struct pci_dev *pdev, if(adapter->hw.mac_type >= e1000_82543) { netdev->features = NETIF_F_SG | - NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_TX | - NETIF_F_HW_VLAN_RX | + NETIF_F_HW_CSUM | + NETIF_F_HW_VLAN_TX | + NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; } else { netdev->features = NETIF_F_SG; } - if(adapter->hw.mac_type >= e1000_82544) + if((adapter->hw.mac_type >= e1000_82544) && + (adapter->hw.mac_type != e1000_82547)) netdev->features |= NETIF_F_TSO; - + if(pci_using_dac) netdev->features |= NETIF_F_HIGHDMA; @@ -461,6 +483,9 @@ e1000_probe(struct pci_dev *pdev, else adapter->max_data_per_txd = MAX_JUMBO_FRAME_SIZE; + init_timer(&adapter->tx_fifo_stall_timer); + adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall; + adapter->tx_fifo_stall_timer.data = (unsigned long) adapter; init_timer(&adapter->watchdog_timer); adapter->watchdog_timer.function = &e1000_watchdog; @@ -490,11 +515,12 @@ e1000_probe(struct pci_dev *pdev, * enable the ACPI Magic Packet filter */ - e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL2_REG, &eeprom_data); + e1000_read_eeprom(&adapter->hw, EEPROM_INIT_CONTROL2_REG,1, &eeprom_data); if((adapter->hw.mac_type >= e1000_82544) && (eeprom_data & E1000_EEPROM_APME)) adapter->wol |= E1000_WUFC_MAG; + /* reset the hardware with the new settings */ e1000_reset(adapter); @@ -586,6 +612,10 @@ e1000_sw_init(struct e1000_adapter *adapter) return -1; } + /* initialize eeprom parameters */ + + e1000_init_eeprom_params(hw); + /* flow control settings */ hw->fc_high_water = E1000_FC_HIGH_THRESH; @@ -593,6 +623,9 @@ e1000_sw_init(struct e1000_adapter *adapter) hw->fc_pause_time = E1000_FC_PAUSE_TIME; hw->fc_send_xon = 1; + if((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) + hw->phy_init_script = 1; + /* Media type - copper or fiber */ if(hw->mac_type >= e1000_82543) { @@ -1192,9 +1225,9 @@ e1000_set_multi(struct net_device *netdev) if(hw->mac_type == e1000_82542_rev2_0) e1000_enter_82542_rst(adapter); - /* load the first 15 multicast address into the exact filters 1-15 + /* load the first 14 multicast address into the exact filters 1-14 * RAR 0 is used for the station MAC adddress - * if there are not 15 addresses, go ahead and clear the filters + * if there are not 14 addresses, go ahead and clear the filters */ mc_ptr = netdev->mc_list; @@ -1234,6 +1267,48 @@ e1000_update_phy_info(unsigned long data) e1000_phy_get_info(&adapter->hw, &adapter->phy_info); } +/** + * e1000_82547_tx_fifo_stall - Timer Call-back + * @data: pointer to adapter cast into an unsigned long + **/ + +static void +e1000_82547_tx_fifo_stall(unsigned long data) +{ + struct e1000_adapter *adapter = (struct e1000_adapter *) data; + struct net_device *netdev = adapter->netdev; + uint32_t tctl; + + if(atomic_read(&adapter->tx_fifo_stall)) { + if((E1000_READ_REG(&adapter->hw, TDT) == + E1000_READ_REG(&adapter->hw, TDH)) && + (E1000_READ_REG(&adapter->hw, TDFT) == + E1000_READ_REG(&adapter->hw, TDFH)) && + (E1000_READ_REG(&adapter->hw, TDFTS) == + E1000_READ_REG(&adapter->hw, TDFHS))) { + tctl = E1000_READ_REG(&adapter->hw, TCTL); + E1000_WRITE_REG(&adapter->hw, TCTL, + tctl & ~E1000_TCTL_EN); + E1000_WRITE_REG(&adapter->hw, TDFT, + adapter->tx_head_addr); + E1000_WRITE_REG(&adapter->hw, TDFH, + adapter->tx_head_addr); + E1000_WRITE_REG(&adapter->hw, TDFTS, + adapter->tx_head_addr); + E1000_WRITE_REG(&adapter->hw, TDFHS, + adapter->tx_head_addr); + E1000_WRITE_REG(&adapter->hw, TCTL, tctl); + E1000_WRITE_FLUSH(&adapter->hw); + + adapter->tx_fifo_head = 0; + atomic_set(&adapter->tx_fifo_stall, 0); + netif_wake_queue(netdev); + } else { + mod_timer(&adapter->tx_fifo_stall_timer, jiffies + 1); + } + } +} + /** * e1000_watchdog - Timer Call-back * @data: pointer to netdev cast into an unsigned long @@ -1264,6 +1339,7 @@ e1000_watchdog(unsigned long data) netif_carrier_on(netdev); netif_wake_queue(netdev); mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ); + adapter->smartspeed = 0; } } else { if(netif_carrier_ok(netdev)) { @@ -1276,6 +1352,8 @@ e1000_watchdog(unsigned long data) netif_stop_queue(netdev); mod_timer(&adapter->phy_info_timer, jiffies + 2 * HZ); } + + e1000_smartspeed(adapter); } e1000_update_stats(adapter); @@ -1501,6 +1579,49 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) } #define TXD_USE_COUNT(S, X) (((S) / (X)) + (((S) % (X)) ? 1 : 0)) +/** + * 82547 workaround to avoid controller hang in half-duplex environment. + * The workaround is to avoid queuing a large packet that would span + * the internal Tx FIFO ring boundary by notifying the stack to resend + * the packet at a later time. This gives the Tx FIFO an opportunity to + * flush all packets. When that occurs, we reset the Tx FIFO pointers + * to the beginning of the Tx FIFO. + **/ + +#define E1000_FIFO_HDR 0x10 +#define E1000_82547_PAD_LEN 0x3E0 + +static inline int +e1000_82547_fifo_workaround(struct e1000_adapter *adapter, struct sk_buff *skb) +{ + uint32_t fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; + uint32_t skb_fifo_len = skb->len + E1000_FIFO_HDR; + + E1000_ROUNDUP(skb_fifo_len, E1000_FIFO_HDR); + + if(adapter->link_duplex != HALF_DUPLEX) + goto no_fifo_stall_required; + + if(atomic_read(&adapter->tx_fifo_stall)) + return 1; + + if(skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { + atomic_set(&adapter->tx_fifo_stall, 1); + return 1; + } + +no_fifo_stall_required: + adapter->tx_fifo_head += skb_fifo_len; + if(adapter->tx_fifo_head >= adapter->tx_fifo_size) + adapter->tx_fifo_head -= adapter->tx_fifo_size; + return 0; +} + +/* Tx Descriptors needed, worst case */ +#define TXD_USE_COUNT(S) (((S) >> E1000_MAX_TXD_PWR) + \ + (((S) & (E1000_MAX_DATA_PER_TXD - 1)) ? 1 : 0)) +#define DESC_NEEDED TXD_USE_COUNT(MAX_JUMBO_FRAME_SIZE) + \ + MAX_SKB_FRAGS * TXD_USE_COUNT(PAGE_SIZE) + 1 static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) @@ -1528,6 +1649,14 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) return 1; } + if(adapter->hw.mac_type == e1000_82547) { + if(e1000_82547_fifo_workaround(adapter, skb)) { + netif_stop_queue(netdev); + mod_timer(&adapter->tx_fifo_stall_timer, jiffies); + return 1; + } + } + if(adapter->vlgrp && vlan_tx_tag_present(skb)) { tx_flags |= E1000_TX_FLAGS_VLAN; tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); @@ -2222,6 +2351,61 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) rx_ring->next_to_use = i; } +/** + * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers. + * @adapter: + **/ + +static void +e1000_smartspeed(struct e1000_adapter *adapter) +{ + uint16_t phy_status; + uint16_t phy_ctrl; + + if((adapter->hw.phy_type != e1000_phy_igp) || !adapter->hw.autoneg || + !(adapter->hw.autoneg_advertised & ADVERTISE_1000_FULL)) + return; + + if(adapter->smartspeed == 0) { + /* If Master/Slave config fault is asserted twice, + * we assume back-to-back */ + e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); + if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; + e1000_read_phy_reg(&adapter->hw, PHY_1000T_STATUS, &phy_status); + if(!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; + e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); + if(phy_ctrl & CR_1000T_MS_ENABLE) { + phy_ctrl &= ~CR_1000T_MS_ENABLE; + e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, + phy_ctrl); + adapter->smartspeed++; + if(!e1000_phy_setup_autoneg(&adapter->hw) && + !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, + &phy_ctrl)) { + phy_ctrl |= (MII_CR_AUTO_NEG_EN | + MII_CR_RESTART_AUTO_NEG); + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, + phy_ctrl); + } + } + return; + } else if(adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { + /* If still no link, perhaps using 2/3 pair cable */ + e1000_read_phy_reg(&adapter->hw, PHY_1000T_CTRL, &phy_ctrl); + phy_ctrl |= CR_1000T_MS_ENABLE; + e1000_write_phy_reg(&adapter->hw, PHY_1000T_CTRL, phy_ctrl); + if(!e1000_phy_setup_autoneg(&adapter->hw) && + !e1000_read_phy_reg(&adapter->hw, PHY_CTRL, &phy_ctrl)) { + phy_ctrl |= (MII_CR_AUTO_NEG_EN | + MII_CR_RESTART_AUTO_NEG); + e1000_write_phy_reg(&adapter->hw, PHY_CTRL, phy_ctrl); + } + } + /* Restart process after E1000_SMARTSPEED_MAX iterations */ + if(adapter->smartspeed++ == E1000_SMARTSPEED_MAX) + adapter->smartspeed = 0; +} + /** * e1000_ioctl - * @netdev: -- cgit v1.2.3 From 6497b3ff86114cc461208e35b7ea1bcc00422438 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:41:34 -0500 Subject: [E1000] Added MII support * Added MII support --- drivers/net/e1000/e1000.h | 1 + drivers/net/e1000/e1000_main.c | 86 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 9efac9fc6775..94c9a08e0573 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -65,6 +65,7 @@ #include #include #include +#include #include #include diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 2590e35a57d4..045843b212b9 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -163,6 +163,8 @@ static void e1000_clean_rx_irq(struct e1000_adapter *adapter); #endif static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); +static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, + int cmd); static void e1000_enter_82542_rst(struct e1000_adapter *adapter); static void e1000_leave_82542_rst(struct e1000_adapter *adapter); static inline void e1000_rx_checksum(struct e1000_adapter *adapter, @@ -2417,6 +2419,10 @@ static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { switch (cmd) { + case SIOCGMIIPHY: + case SIOCGMIIREG: + case SIOCSMIIREG: + return e1000_mii_ioctl(netdev, ifr, cmd); case SIOCETHTOOL: return e1000_ethtool_ioctl(netdev, ifr); default: @@ -2424,6 +2430,86 @@ e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) } } +/** + * e1000_mii_ioctl - + * @netdev: + * @ifreq: + * @cmd: + **/ + +static int +e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) +{ + struct e1000_adapter *adapter = netdev->priv; + struct mii_ioctl_data *data = (struct mii_ioctl_data *)&ifr->ifr_data; + int retval; + uint16_t mii_reg; + uint16_t spddplx; + + if(adapter->hw.media_type == e1000_media_type_fiber) + return -EOPNOTSUPP; + + switch (cmd) { + case SIOCGMIIPHY: + data->phy_id = adapter->hw.phy_addr; + break; + case SIOCGMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (e1000_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, + &data->val_out)) + return -EIO; + break; + case SIOCSMIIREG: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + if (data->reg_num & ~(0x1F)) + return -EFAULT; + mii_reg = data->val_in; + if (e1000_write_phy_reg(&adapter->hw, data->reg_num, + data->val_in)) + return -EIO; + if (adapter->hw.phy_type == e1000_phy_m88) { + switch (data->reg_num) { + case PHY_CTRL: + if(data->val_in & MII_CR_AUTO_NEG_EN) { + adapter->hw.autoneg = 1; + adapter->hw.autoneg_advertised = 0x2F; + } else { + if (data->val_in & 0x40) + spddplx = SPEED_1000; + else if (data->val_in & 0x2000) + spddplx = SPEED_100; + else + spddplx = SPEED_10; + spddplx += (data->val_in & 0x100) + ? FULL_DUPLEX : + HALF_DUPLEX; + retval = e1000_set_spd_dplx(adapter, + spddplx); + if(retval) + return retval; + } + if(netif_running(adapter->netdev)) { + e1000_down(adapter); + e1000_up(adapter); + } else + e1000_reset(adapter); + break; + case M88E1000_PHY_SPEC_CTRL: + case M88E1000_EXT_PHY_SPEC_CTRL: + if (e1000_phy_reset(&adapter->hw)) + return -EIO; + break; + } + } + break; + default: + return -EOPNOTSUPP; + } + return E1000_SUCCESS; +} + /** * e1000_rx_checksum - Receive Checksum Offload for 82543 * @adapter: board private structure -- cgit v1.2.3 From 35d75fa00ab02ceb268a42273506a5385e147cd7 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:41:59 -0500 Subject: [E1000] Modulus math removed * Removed modulus math; decreases CPU utilization, especially on PPC64 [anton@samba.org] --- drivers/net/e1000/e1000.h | 6 +-- drivers/net/e1000/e1000_main.c | 86 ++++++++++++++---------------------------- 2 files changed, 32 insertions(+), 60 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 94c9a08e0573..1c3ae0c55fb3 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -117,7 +117,7 @@ struct e1000_adapter; /* How many Tx Descriptors do we need to call netif_wake_queue ? */ #define E1000_TX_QUEUE_WAKE 16 /* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define E1000_RX_BUFFER_WRITE 16 +#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ #define AUTO_ALL_MODES 0 #define E1000_EEPROM_APME 4 @@ -152,7 +152,8 @@ struct e1000_desc_ring { }; #define E1000_DESC_UNUSED(R) \ -((((R)->next_to_clean + (R)->count) - ((R)->next_to_use + 1)) % ((R)->count)) + ((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \ + (R)->next_to_clean - (R)->next_to_use - 1) #define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) #define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) @@ -186,7 +187,6 @@ struct e1000_adapter { uint32_t txd_cmd; uint32_t tx_int_delay; uint32_t tx_abs_int_delay; - int max_data_per_txd; uint32_t tx_fifo_head; uint32_t tx_head_addr; uint32_t tx_fifo_size; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 045843b212b9..de48b65481f0 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -155,12 +155,8 @@ static void e1000_update_stats(struct e1000_adapter *adapter); static inline void e1000_irq_disable(struct e1000_adapter *adapter); static inline void e1000_irq_enable(struct e1000_adapter *adapter); static void e1000_intr(int irq, void *data, struct pt_regs *regs); -static void e1000_clean_tx_irq(struct e1000_adapter *adapter); -#ifdef CONFIG_E1000_NAPI -static int e1000_poll(struct net_device *netdev, int *budget); -#else -static void e1000_clean_rx_irq(struct e1000_adapter *adapter); -#endif +static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); +static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter); static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, @@ -420,10 +416,6 @@ e1000_probe(struct pci_dev *pdev, netdev->change_mtu = &e1000_change_mtu; netdev->do_ioctl = &e1000_ioctl; netdev->tx_timeout = &e1000_tx_timeout; -#ifdef CONFIG_E1000_NAPI - netdev->poll = &e1000_poll; - netdev->weight = 64; -#endif netdev->watchdog_timeo = 5 * HZ; netdev->vlan_rx_register = e1000_vlan_rx_register; netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; @@ -478,13 +470,6 @@ e1000_probe(struct pci_dev *pdev, e1000_get_bus_info(&adapter->hw); - if((adapter->hw.mac_type == e1000_82544) && - (adapter->hw.bus_type == e1000_bus_type_pcix)) - - adapter->max_data_per_txd = 4096; - else - adapter->max_data_per_txd = MAX_JUMBO_FRAME_SIZE; - init_timer(&adapter->tx_fifo_stall_timer); adapter->tx_fifo_stall_timer.function = &e1000_82547_tx_fifo_stall; adapter->tx_fifo_stall_timer.data = (unsigned long) adapter; @@ -1423,12 +1408,12 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags) E1000_TXD_CMD_IP | E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); - i = (i + 1) % adapter->tx_ring.count; + if(++i == adapter->tx_ring.count) i = 0; adapter->tx_ring.next_to_use = i; return TRUE; } - + return FALSE; } @@ -1453,7 +1438,7 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) context_desc->cmd_and_length = cpu_to_le32(adapter->txd_cmd | E1000_TXD_CMD_DEXT); - i = (i + 1) % adapter->tx_ring.count; + if(++i == adapter->tx_ring.count) i = 0; adapter->tx_ring.next_to_use = i; return TRUE; @@ -1462,24 +1447,24 @@ e1000_tx_csum(struct e1000_adapter *adapter, struct sk_buff *skb) return FALSE; } +#define E1000_MAX_TXD_PWR 12 +#define E1000_MAX_DATA_PER_TXD (1<tx_ring; - int len, offset, size, count, i; + int len = skb->len, offset = 0, size, count = 0, i; + int tso = skb_shinfo(skb)->tso_size; int nr_frags = skb_shinfo(skb)->nr_frags; - int f; - len = skb->len - skb->data_len; - i = (tx_ring->next_to_use + tx_ring->count - 1) % tx_ring->count; - count = 0; + len -= skb->data_len; - offset = 0; + i = tx_ring->next_to_use; while(len) { - i = (i + 1) % tx_ring->count; - size = min(len, adapter->max_data_per_txd); + size = min(len, E1000_MAX_DATA_PER_TXD); /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ if(tso && !nr_frags && size == len && size > 4) @@ -1495,6 +1480,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb) len -= size; offset += size; count++; + if(++i == tx_ring->count) i = 0; } for(f = 0; f < nr_frags; f++) { @@ -1505,8 +1491,7 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb) offset = 0; while(len) { - i = (i + 1) % tx_ring->count; - size = min(len, adapter->max_data_per_txd); + size = min(len, E1000_MAX_DATA_PER_TXD); /* Workaround for premature desc write-backs * in TSO mode. Append 4-byte sentinel desc */ if(tso && f == (nr_frags-1) && size == len && size > 4) @@ -1523,8 +1508,10 @@ e1000_tx_map(struct e1000_adapter *adapter, struct sk_buff *skb) len -= size; offset += size; count++; + if(++i == tx_ring->count) i = 0; } } + if(--i < 0) i = tx_ring->count - 1; tx_ring->buffer_info[i].skb = skb; return count; @@ -1565,7 +1552,7 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) tx_desc->lower.data = cpu_to_le32(txd_lower | tx_ring->buffer_info[i].length); tx_desc->upper.data = cpu_to_le32(txd_upper); - i = (i + 1) % tx_ring->count; + if(++i == tx_ring->count) i = 0; } tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP); @@ -1580,7 +1567,6 @@ e1000_tx_queue(struct e1000_adapter *adapter, int count, int tx_flags) E1000_WRITE_REG(&adapter->hw, TDT, i); } -#define TXD_USE_COUNT(S, X) (((S) / (X)) + (((S) % (X)) ? 1 : 0)) /** * 82547 workaround to avoid controller hang in half-duplex environment. * The workaround is to avoid queuing a large packet that would span @@ -1629,24 +1615,14 @@ static int e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) { struct e1000_adapter *adapter = netdev->priv; - int tx_flags = 0, count; - int f; + int tx_flags = 0; - count = TXD_USE_COUNT(skb->len - skb->data_len, - adapter->max_data_per_txd); - - if(count == 0) { + if(skb->len <= 0) { dev_kfree_skb_any(skb); return 0; } - for(f = 0; f < skb_shinfo(skb)->nr_frags; f++) - count += TXD_USE_COUNT(skb_shinfo(skb)->frags[f].size, - adapter->max_data_per_txd); - if((skb_shinfo(skb)->tso_size) || (skb->ip_summed == CHECKSUM_HW)) - count++; - - if(E1000_DESC_UNUSED(&adapter->tx_ring) < count) { + if(E1000_DESC_UNUSED(&adapter->tx_ring) < DESC_NEEDED) { netif_stop_queue(netdev); return 1; } @@ -1669,9 +1645,7 @@ e1000_xmit_frame(struct sk_buff *skb, struct net_device *netdev) else if(e1000_tx_csum(adapter, skb)) tx_flags |= E1000_TX_FLAGS_CSUM; - count = e1000_tx_map(adapter, skb); - - e1000_tx_queue(adapter, count, tx_flags); + e1000_tx_queue(adapter, e1000_tx_map(adapter, skb), tx_flags); netdev->trans_start = jiffies; @@ -2041,7 +2015,7 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) tx_desc->upper.data = 0; - i = (i + 1) % tx_ring->count; + if(++i == tx_ring->count) i = 0; tx_desc = E1000_TX_DESC(*tx_ring, i); } @@ -2225,7 +2199,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) rx_desc->status = 0; rx_ring->buffer_info[i].skb = NULL; - i = (i + 1) % rx_ring->count; + if(++i == rx_ring->count) i = 0; rx_desc = E1000_RX_DESC(*rx_ring, i); continue; @@ -2253,7 +2227,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) rx_desc->status = 0; rx_ring->buffer_info[i].skb = NULL; - i = (i + 1) % rx_ring->count; + if(++i == rx_ring->count) i = 0; rx_desc = E1000_RX_DESC(*rx_ring, i); continue; @@ -2278,7 +2252,7 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) rx_desc->status = 0; rx_ring->buffer_info[i].skb = NULL; - i = (i + 1) % rx_ring->count; + if(++i == rx_ring->count) i = 0; rx_desc = E1000_RX_DESC(*rx_ring, i); } @@ -2302,11 +2276,9 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) struct pci_dev *pdev = adapter->pdev; struct e1000_rx_desc *rx_desc; struct sk_buff *skb; - int reserve_len; + int reserve_len = 2; int i; - reserve_len = 2; - i = rx_ring->next_to_use; while(!rx_ring->buffer_info[i].skb) { @@ -2337,7 +2309,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) rx_desc->buffer_addr = cpu_to_le64(rx_ring->buffer_info[i].dma); - if(!(i % E1000_RX_BUFFER_WRITE)) { + if((i & ~(E1000_RX_BUFFER_WRITE - 1)) == i) { /* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, @@ -2347,7 +2319,7 @@ e1000_alloc_rx_buffers(struct e1000_adapter *adapter) E1000_WRITE_REG(&adapter->hw, RDT, i); } - i = (i + 1) % rx_ring->count; + if(++i == rx_ring->count) i = 0; } rx_ring->next_to_use = i; -- cgit v1.2.3 From fd1a461e845c5d8669a4b9457bdaeda44abffd82 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:42:24 -0500 Subject: [E1000] Perform single PCI read per interrupt * ISR cleanup; performing single PCI read --- drivers/net/e1000/e1000_main.c | 211 +++++------------------------------------ 1 file changed, 23 insertions(+), 188 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index de48b65481f0..b7dc6bb88616 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1920,82 +1920,45 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) { struct net_device *netdev = data; struct e1000_adapter *adapter = netdev->priv; - -#ifdef CONFIG_E1000_NAPI - if (netif_rx_schedule_prep(netdev)) { - /* Disable interrupts and enable polling */ - atomic_inc(&adapter->irq_sem); - E1000_WRITE_REG(&adapter->hw, IMC, ~0); - E1000_WRITE_FLUSH(&adapter->hw); - __netif_rx_schedule(netdev); - } -#else - uint32_t icr; - int i = E1000_MAX_INTR; - - while(i && (icr = E1000_READ_REG(&adapter->hw, ICR))) { - - if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { - adapter->hw.get_link_status = 1; - mod_timer(&adapter->watchdog_timer, jiffies); - } + uint32_t icr = E1000_READ_REG(&adapter->hw, ICR); + int i; - e1000_clean_rx_irq(adapter); - e1000_clean_tx_irq(adapter); - i--; + if(!icr) + return; /* Not our interrupt */ + if(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { + adapter->hw.get_link_status = 1; + mod_timer(&adapter->watchdog_timer, jiffies); } -#endif -} -#ifdef CONFIG_E1000_NAPI -static int -e1000_process_intr(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev->priv; - uint32_t icr; - int i = E1000_MAX_INTR; - int hasReceived = 0; - - while(i && (icr = E1000_READ_REG(&adapter->hw, ICR))) { - if (icr & E1000_ICR_RXT0) - hasReceived = 1; - - if (!(icr & ~(E1000_ICR_RXT0))) + for(i = 0; i < E1000_MAX_INTR; i++) + if(!e1000_clean_rx_irq(adapter) && + !e1000_clean_tx_irq(adapter)) break; - - if (icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC)) { - adapter->hw.get_link_status = 1; - mod_timer(&adapter->watchdog_timer, jiffies); - } - - e1000_clean_tx_irq(adapter); - i--; - } - return hasReceived; } -#endif /** * e1000_clean_tx_irq - Reclaim resources after transmit completes * @adapter: board private structure **/ -static void +static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter) { struct e1000_desc_ring *tx_ring = &adapter->tx_ring; struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; struct e1000_tx_desc *tx_desc; - int i; + int i, cleaned = FALSE; i = tx_ring->next_to_clean; tx_desc = E1000_TX_DESC(*tx_ring, i); while(tx_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) { + cleaned = TRUE; + if(tx_ring->buffer_info[i].dma) { pci_unmap_page(pdev, @@ -2021,149 +1984,18 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) tx_ring->next_to_clean = i; - if(netif_queue_stopped(netdev) && netif_carrier_ok(netdev) && - (E1000_DESC_UNUSED(tx_ring) > E1000_TX_QUEUE_WAKE)) { - + if(cleaned && netif_queue_stopped(netdev) && netif_carrier_ok(netdev)) netif_wake_queue(netdev); - } -} - -#ifdef CONFIG_E1000_NAPI -static int -e1000_poll(struct net_device *netdev, int *budget) -{ - struct e1000_adapter *adapter = netdev->priv; - struct e1000_desc_ring *rx_ring = &adapter->rx_ring; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc; - struct sk_buff *skb; - unsigned long flags; - uint32_t length; - uint8_t last_byte; - int i; - int received = 0; - int rx_work_limit = *budget; - - if(rx_work_limit > netdev->quota) - rx_work_limit = netdev->quota; - - e1000_process_intr(netdev); - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC(*rx_ring, i); - - while(rx_desc->status & E1000_RXD_STAT_DD) { - if(--rx_work_limit < 0) - goto not_done; - - pci_unmap_single(pdev, - rx_ring->buffer_info[i].dma, - rx_ring->buffer_info[i].length, - PCI_DMA_FROMDEVICE); - - skb = rx_ring->buffer_info[i].skb; - length = le16_to_cpu(rx_desc->length); - - if(!(rx_desc->status & E1000_RXD_STAT_EOP)) { - - /* All receives must fit into a single buffer */ - - E1000_DBG("Receive packet consumed multiple buffers\n"); - - dev_kfree_skb_irq(skb); - rx_desc->status = 0; - rx_ring->buffer_info[i].skb = NULL; - - i = (i + 1) % rx_ring->count; - - rx_desc = E1000_RX_DESC(*rx_ring, i); - continue; - } - - if(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) { - - last_byte = *(skb->data + length - 1); - - if(TBI_ACCEPT(&adapter->hw, rx_desc->status, - rx_desc->errors, length, last_byte)) { - - spin_lock_irqsave(&adapter->stats_lock, flags); - - e1000_tbi_adjust_stats(&adapter->hw, - &adapter->stats, - length, skb->data); - - spin_unlock_irqrestore(&adapter->stats_lock, - flags); - length--; - } else { - - dev_kfree_skb_irq(skb); - rx_desc->status = 0; - rx_ring->buffer_info[i].skb = NULL; - - i = (i + 1) % rx_ring->count; - - rx_desc = E1000_RX_DESC(*rx_ring, i); - continue; - } - } - - /* Good Receive */ - skb_put(skb, length - ETHERNET_FCS_SIZE); - - /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, rx_desc, skb); - - skb->protocol = eth_type_trans(skb, netdev); - if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { - vlan_hwaccel_rx(skb, adapter->vlgrp, - (rx_desc->special & E1000_RXD_SPC_VLAN_MASK)); - } else { - netif_receive_skb(skb); - } - netdev->last_rx = jiffies; - - rx_desc->status = 0; - rx_ring->buffer_info[i].skb = NULL; - i = (i + 1) % rx_ring->count; - - rx_desc = E1000_RX_DESC(*rx_ring, i); - received++; - } - - if(!received) - received = 1; - - e1000_alloc_rx_buffers(adapter); - - rx_ring->next_to_clean = i; - netdev->quota -= received; - *budget -= received; - - netif_rx_complete(netdev); - - e1000_irq_enable(adapter); - return 0; - -not_done: - - e1000_alloc_rx_buffers(adapter); - - rx_ring->next_to_clean = i; - netdev->quota -= received; - *budget -= received; - - return 1; + return cleaned; } -#else + /** * e1000_clean_rx_irq - Send received data up the network stack, * @adapter: board private structure **/ -static void +static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter) { struct e1000_desc_ring *rx_ring = &adapter->rx_ring; @@ -2174,13 +2006,15 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) unsigned long flags; uint32_t length; uint8_t last_byte; - int i; + int i, cleaned = FALSE; i = rx_ring->next_to_clean; rx_desc = E1000_RX_DESC(*rx_ring, i); while(rx_desc->status & E1000_RXD_STAT_DD) { + cleaned = TRUE; + pci_unmap_single(pdev, rx_ring->buffer_info[i].dma, rx_ring->buffer_info[i].length, @@ -2260,8 +2094,9 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) rx_ring->next_to_clean = i; e1000_alloc_rx_buffers(adapter); + + return cleaned; } -#endif /** * e1000_alloc_rx_buffers - Replace used receive buffers -- cgit v1.2.3 From f4630b19f8c3fb6524c0f3c2087cd8d3c206e1ee Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:42:48 -0500 Subject: [E1000] Tx Descriptor cleanup * Completely clean Tx descriptor to avoid potential dirty descriptor fetching (rare, but possible) --- drivers/net/e1000/e1000_main.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b7dc6bb88616..99180119b986 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1976,6 +1976,8 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) tx_ring->buffer_info[i].skb = NULL; } + tx_desc->buffer_addr = 0; + tx_desc->lower.data = 0; tx_desc->upper.data = 0; if(++i == tx_ring->count) i = 0; -- cgit v1.2.3 From 3771495b0a3563cadf230f6ec4ea0903284ad892 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:43:13 -0500 Subject: [E1000] Read/Write register macro optimizations * Optimized E1000_*_REG macros --- drivers/net/e1000/e1000_osdep.h | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_osdep.h b/drivers/net/e1000/e1000_osdep.h index 05b1518aa74d..fe351959ed47 100644 --- a/drivers/net/e1000/e1000_osdep.h +++ b/drivers/net/e1000/e1000_osdep.h @@ -77,24 +77,22 @@ typedef enum { #define E1000_WRITE_REG(a, reg, value) ( \ - ((a)->mac_type >= e1000_82543) ? \ - (writel((value), ((a)->hw_addr + E1000_##reg))) : \ - (writel((value), ((a)->hw_addr + E1000_82542_##reg)))) + writel((value), ((a)->hw_addr + \ + (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg)))) #define E1000_READ_REG(a, reg) ( \ - ((a)->mac_type >= e1000_82543) ? \ - readl((a)->hw_addr + E1000_##reg) : \ - readl((a)->hw_addr + E1000_82542_##reg)) + readl((a)->hw_addr + \ + (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg))) #define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ - ((a)->mac_type >= e1000_82543) ? \ - writel((value), ((a)->hw_addr + E1000_##reg + ((offset) << 2))) : \ - writel((value), ((a)->hw_addr + E1000_82542_##reg + ((offset) << 2)))) + writel((value), ((a)->hw_addr + \ + (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ + ((offset) << 2)))) #define E1000_READ_REG_ARRAY(a, reg, offset) ( \ - ((a)->mac_type >= e1000_82543) ? \ - readl((a)->hw_addr + E1000_##reg + ((offset) << 2)) : \ - readl((a)->hw_addr + E1000_82542_##reg + ((offset) << 2))) + readl((a)->hw_addr + \ + (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ + ((offset) << 2))) #define E1000_WRITE_FLUSH(a) E1000_READ_REG(a, STATUS) -- cgit v1.2.3 From 85beee792efa6ea5e3400d272f96f4ef1d87446a Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:43:38 -0500 Subject: [E1000] Compaq to HP branding change * Changed "Compaq" branding to "HP" --- drivers/net/e1000/e1000_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 99180119b986..cee1eabe9c25 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -116,7 +116,7 @@ MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); static char *e1000_strings[] = { "Intel(R) PRO/1000 Network Connection", - "Compaq Gigabit Ethernet Server Adapter", + "HP Gigabit Ethernet Server Adapter", "IBM Mobile, Desktop & Server Adapters" }; -- cgit v1.2.3 From 8bf752eb64f7a348c4b30db4f67e0f40d2fc46c9 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:44:04 -0500 Subject: [E1000] Whitespace changes * Miscellaneous whitespace changes --- drivers/net/e1000/e1000_ethtool.c | 6 +- drivers/net/e1000/e1000_hw.c | 127 +++++++++++++++++++------------------- drivers/net/e1000/e1000_hw.h | 42 +++++++------ drivers/net/e1000/e1000_main.c | 15 +++-- drivers/net/e1000/e1000_param.c | 49 ++++++++------- 5 files changed, 124 insertions(+), 115 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_ethtool.c b/drivers/net/e1000/e1000_ethtool.c index 426101fa0a2b..c64530107467 100644 --- a/drivers/net/e1000/e1000_ethtool.c +++ b/drivers/net/e1000/e1000_ethtool.c @@ -308,8 +308,8 @@ e1000_ethtool_gwol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) /* Fall Through */ default: - wol->supported = WAKE_UCAST | WAKE_MCAST - | WAKE_BCAST | WAKE_MAGIC; + wol->supported = WAKE_UCAST | WAKE_MCAST | + WAKE_BCAST | WAKE_MAGIC; wol->wolopts = 0; if(adapter->wol & E1000_WUFC_EX) @@ -343,7 +343,7 @@ e1000_ethtool_swol(struct e1000_adapter *adapter, struct ethtool_wolinfo *wol) /* Fall Through */ default: - if(wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | WAKE_PHY)) + if(wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) return -EOPNOTSUPP; adapter->wol = 0; diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 56b315bc00a9..193bfe98f0ed 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -241,7 +241,7 @@ e1000_reset_hw(struct e1000_hw *hw) /* Delay to allow any outstanding PCI transactions to complete before * resetting the device - */ + */ msec_delay(10); /* Issue a global reset to the MAC. This will reset the chip's @@ -312,8 +312,8 @@ e1000_reset_hw(struct e1000_hw *hw) * Performs basic configuration of the adapter. * * hw - Struct containing variables accessed by shared code - * - * Assumes that the controller has previously been reset and is in a + * + * Assumes that the controller has previously been reset and is in a * post-reset uninitialized state. Initializes the receive address registers, * multicast table, and VLAN filter table. Calls routines to setup link * configuration and flow control settings. Clears all on-chip counters. Leaves @@ -338,7 +338,7 @@ e1000_init_hw(struct e1000_hw *hw) DEBUGOUT("Error Initializing Identification LED\n"); return ret_val; } - + /* Set the Media Type and exit with error if it is not valid. */ if(hw->mac_type != e1000_82543) { /* tbi_compatibility is only valid on 82543 */ @@ -441,13 +441,13 @@ e1000_init_hw(struct e1000_hw *hw) /****************************************************************************** * Configures flow control and link settings. - * + * * hw - Struct containing variables accessed by shared code - * + * * Determines which flow control settings to use. Calls the apropriate media- * specific link configuration function. Configures the flow control settings. * Assuming the adapter has a valid link partner, a valid link should be - * established. Assumes the hardware has previously been reset and the + * established. Assumes the hardware has previously been reset and the * transmitter and receiver are not enabled. *****************************************************************************/ int32_t @@ -475,7 +475,7 @@ e1000_setup_link(struct e1000_hw *hw) if(hw->fc == e1000_fc_default) { if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) hw->fc = e1000_fc_none; - else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == + else if((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == EEPROM_WORD0F_ASM_DIR) hw->fc = e1000_fc_tx_pause; else @@ -504,7 +504,7 @@ e1000_setup_link(struct e1000_hw *hw) * or e1000_phy_setup() is called. */ if(hw->mac_type == e1000_82543) { - ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << + ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << SWDPIO__EXT_SHIFT); E1000_WRITE_REG(hw, CTRL_EXT, ctrl_ext); } @@ -530,7 +530,7 @@ e1000_setup_link(struct e1000_hw *hw) * these registers will be set to a default threshold that may be * adjusted later by the driver's runtime code. However, if the * ability to transmit pause frames in not enabled, then these - * registers will be set to 0. + * registers will be set to 0. */ if(!(hw->fc & e1000_fc_tx_pause)) { E1000_WRITE_REG(hw, FCRTL, 0); @@ -559,7 +559,7 @@ e1000_setup_link(struct e1000_hw *hw) * link. Assumes the hardware has been previously reset and the transmitter * and receiver are not enabled. *****************************************************************************/ -static int32_t +static int32_t e1000_setup_fiber_link(struct e1000_hw *hw) { uint32_t ctrl; @@ -571,29 +571,29 @@ e1000_setup_fiber_link(struct e1000_hw *hw) DEBUGFUNC("e1000_setup_fiber_link"); - /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be - * set when the optics detect a signal. On older adapters, it will be + /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be + * set when the optics detect a signal. On older adapters, it will be * cleared when there is a signal */ ctrl = E1000_READ_REG(hw, CTRL); if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1; else signal = 0; - + /* Take the link out of reset */ ctrl &= ~(E1000_CTRL_LRST); - + e1000_config_collision_dist(hw); /* Check for a software override of the flow control settings, and setup * the device accordingly. If auto-negotiation is enabled, then software * will have to set the "PAUSE" bits to the correct value in the Tranmsit * Config Word Register (TXCW) and re-start auto-negotiation. However, if - * auto-negotiation is disabled, then software will have to manually + * auto-negotiation is disabled, then software will have to manually * configure the two flow control enable bits in the CTRL register. * * The possible values of the "fc" parameter are: * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, but + * 1: Rx flow control is enabled (we can receive pause frames, but * not send pause frames). * 2: Tx flow control is enabled (we can send pause frames but we do * not support receiving pause frames). @@ -605,8 +605,8 @@ e1000_setup_fiber_link(struct e1000_hw *hw) txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); break; case e1000_fc_rx_pause: - /* RX Flow control is enabled and TX Flow control is disabled by a - * software over-ride. Since there really isn't a way to advertise + /* RX Flow control is enabled and TX Flow control is disabled by a + * software over-ride. Since there really isn't a way to advertise * that we are capable of RX Pause ONLY, we will advertise that we * support both symmetric and asymmetric RX PAUSE. Later, we will * disable the adapter's ability to send PAUSE frames. @@ -614,7 +614,7 @@ e1000_setup_fiber_link(struct e1000_hw *hw) txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); break; case e1000_fc_tx_pause: - /* TX Flow control is enabled, and RX Flow control is disabled, by a + /* TX Flow control is enabled, and RX Flow control is disabled, by a * software over-ride. */ txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); @@ -645,8 +645,8 @@ e1000_setup_fiber_link(struct e1000_hw *hw) msec_delay(1); /* If we have a signal (the cable is plugged in) then poll for a "Link-Up" - * indication in the Device Status Register. Time-out if a link isn't - * seen in 500 milliseconds seconds (Auto-negotiation should complete in + * indication in the Device Status Register. Time-out if a link isn't + * seen in 500 milliseconds seconds (Auto-negotiation should complete in * less than 500 milliseconds even if the other end is doing it in SW). */ if((E1000_READ_REG(hw, CTRL) & E1000_CTRL_SWDPIN1) == signal) { @@ -657,7 +657,7 @@ e1000_setup_fiber_link(struct e1000_hw *hw) if(status & E1000_STATUS_LU) break; } if(i == (LINK_UP_TIMEOUT / 10)) { - /* AutoNeg failed to achieve a link, so we'll call + /* AutoNeg failed to achieve a link, so we'll call * e1000_check_for_link. This routine will force the link up if we * detect a signal. This will allow us to communicate with * non-autonegotiating link partners. @@ -1266,7 +1266,7 @@ if (hw->phy_type == e1000_phy_m88) { } if(i == 0) { /* We didn't get link */ /* Reset the DSP and wait again for link. */ - + ret_val = e1000_phy_reset_dsp(hw); if(ret_val < 0) { DEBUGOUT("Error Resetting PHY DSP\n"); @@ -1417,7 +1417,7 @@ if (hw->phy_type == e1000_phy_igp) { /****************************************************************************** * Forces the MAC's flow control settings. - * + * * hw - Struct containing variables accessed by shared code * * Sets the TFCE and RFCE bits in the device control register to reflect @@ -1484,7 +1484,7 @@ e1000_force_mac_fc(struct e1000_hw *hw) /****************************************************************************** * Configures flow control settings after link is established - * + * * hw - Struct containing variables accessed by shared code * * Should be called immediately after a valid link has been established. @@ -1706,9 +1706,9 @@ e1000_check_for_link(struct e1000_hw *hw) uint16_t lp_capability; DEBUGFUNC("e1000_check_for_link"); - - /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be - * set when the optics detect a signal. On older adapters, it will be + + /* On adapters with a MAC newer that 82544, SW Defineable pin 1 will be + * set when the optics detect a signal. On older adapters, it will be * cleared when there is a signal */ if(hw->mac_type > e1000_82544) signal = E1000_CTRL_SWDPIN1; @@ -1773,7 +1773,7 @@ e1000_check_for_link(struct e1000_hw *hw) } } - /* Configure Flow Control now that Auto-Neg has completed. First, we + /* Configure Flow Control now that Auto-Neg has completed. First, we * need to restore the desired flow control settings because we may * have had to re-autoneg with a different link partner. */ @@ -1802,7 +1802,7 @@ e1000_check_for_link(struct e1000_hw *hw) NWAY_LPAR_100TX_HD_CAPS | NWAY_LPAR_100TX_FD_CAPS | NWAY_LPAR_100T4_CAPS)) { - /* If our link partner advertises anything in addition to + /* If our link partner advertises anything in addition to * gigabit, we do not need to enable TBI compatibility. */ if(hw->tbi_compatibility_on) { @@ -2006,7 +2006,7 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw, uint32_t mask; /* We need to shift "count" number of bits out to the PHY. So, the value - * in the "data" parameter will be shifted out to the PHY one bit at a + * in the "data" parameter will be shifted out to the PHY one bit at a * time. In order to do this, "data" must be broken down into bits. */ mask = 0x01; @@ -2043,7 +2043,7 @@ e1000_shift_out_mdi_bits(struct e1000_hw *hw, * * hw - Struct containing variables accessed by shared code * -* Bits are shifted in in MSB to LSB order. +* Bits are shifted in in MSB to LSB order. ******************************************************************************/ static uint16_t e1000_shift_in_mdi_bits(struct e1000_hw *hw) @@ -2058,7 +2058,7 @@ e1000_shift_in_mdi_bits(struct e1000_hw *hw) * These two bits are ignored by us and thrown away. Bits are "shifted in" * by raising the input to the Management Data Clock (setting the MDC bit), * and then reading the value of the MDIO bit. - */ + */ ctrl = E1000_READ_REG(hw, CTRL); /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as input. */ @@ -2118,7 +2118,7 @@ e1000_read_phy_reg(struct e1000_hw *hw, * PHY to retrieve the desired data. */ mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | + (phy_addr << E1000_MDIC_PHY_SHIFT) | (E1000_MDIC_OP_READ)); E1000_WRITE_REG(hw, MDIC, mdic); @@ -2156,7 +2156,7 @@ e1000_read_phy_reg(struct e1000_hw *hw, * READ operation is performed. These two bits are thrown away * followed by a shift in of 16 bits which contains the desired data. */ - mdic = ((reg_addr) | (phy_addr << 5) | + mdic = ((reg_addr) | (phy_addr << 5) | (PHY_OP_READ << 10) | (PHY_SOF << 12)); e1000_shift_out_mdi_bits(hw, mdic, 14); @@ -2200,7 +2200,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, */ mdic = (((uint32_t) phy_data) | (reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | + (phy_addr << E1000_MDIC_PHY_SHIFT) | (E1000_MDIC_OP_WRITE)); E1000_WRITE_REG(hw, MDIC, mdic); @@ -2218,12 +2218,12 @@ e1000_write_phy_reg(struct e1000_hw *hw, } else { /* We'll need to use the SW defined pins to shift the write command * out to the PHY. We first send a preamble to the PHY to signal the - * beginning of the MII instruction. This is done by sending 32 + * beginning of the MII instruction. This is done by sending 32 * consecutive "1" bits. */ e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - /* Now combine the remaining required fields that will indicate a + /* Now combine the remaining required fields that will indicate a * write operation. We use this method instead of calling the * e1000_shift_out_mdi_bits routine for each field in the command. The * format of a MII write instruction is as follows: @@ -2236,6 +2236,7 @@ e1000_write_phy_reg(struct e1000_hw *hw, e1000_shift_out_mdi_bits(hw, mdic, 32); } + return 0; } @@ -2393,7 +2394,7 @@ e1000_phy_reset_dsp(struct e1000_hw *hw) { int32_t ret_val = -E1000_ERR_PHY; DEBUGFUNC("e1000_phy_reset_dsp"); - + do { if(e1000_write_phy_reg(hw, 29, 0x001d) < 0) break; if(e1000_write_phy_reg(hw, 30, 0x00c1) < 0) break; @@ -3125,7 +3126,7 @@ e1000_validate_eeprom_checksum(struct e1000_hw *hw) if(checksum == (uint16_t) EEPROM_SUM) { return 0; } else { - DEBUGOUT("EEPROM Checksum Invalid\n"); + DEBUGOUT("EEPROM Checksum Invalid\n"); return -E1000_ERR_EEPROM; } } @@ -3431,7 +3432,7 @@ e1000_read_mac_addr(struct e1000_hw * hw) /****************************************************************************** * Initializes receive address filters. * - * hw - Struct containing variables accessed by shared code + * hw - Struct containing variables accessed by shared code * * Places the MAC address in receive address register 0 and clears the rest * of the receive addresss registers. Clears the multicast table. Assumes @@ -3476,7 +3477,7 @@ e1000_init_rx_addrs(struct e1000_hw *hw) * * The given list replaces any existing list. Clears the last 15 receive * address registers and the multicast table. Uses receive address registers - * for the first 15 multicast addresses, and hashes the rest into the + * for the first 15 multicast addresses, and hashes the rest into the * multicast table. *****************************************************************************/ void @@ -3525,7 +3526,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw, DEBUGOUT1(" Hash value = 0x%03X\n", hash_value); /* Place this multicast address in the RAR if there is room, * - * else put it in the MTA + * else put it in the MTA */ if(rar_used_count < E1000_RAR_ENTRIES) { e1000_rar_set(hw, @@ -3543,7 +3544,7 @@ e1000_mc_addr_list_update(struct e1000_hw *hw, * Hashes an address to determine its location in the multicast table * * hw - Struct containing variables accessed by shared code - * mc_addr - the multicast address to hash + * mc_addr - the multicast address to hash *****************************************************************************/ uint32_t e1000_hash_mc_addr(struct e1000_hw *hw, @@ -3552,7 +3553,7 @@ e1000_hash_mc_addr(struct e1000_hw *hw, uint32_t hash_value = 0; /* The portion of the address that is used for the hash table is - * determined by the mc_filter_type setting. + * determined by the mc_filter_type setting. */ switch (hw->mc_filter_type) { /* [0] [1] [2] [3] [4] [5] @@ -3595,12 +3596,12 @@ e1000_mta_set(struct e1000_hw *hw, uint32_t mta; uint32_t temp; - /* The MTA is a register array of 128 32-bit registers. - * It is treated like an array of 4096 bits. We want to set + /* The MTA is a register array of 128 32-bit registers. + * It is treated like an array of 4096 bits. We want to set * bit BitArray[hash_value]. So we figure out what register * the bit is in, read it, OR in the new bit, then write - * back the new value. The register is determined by the - * upper 7 bits of the hash value and the bit within that + * back the new value. The register is determined by the + * upper 7 bits of the hash value and the bit within that * register are determined by the lower 5 bits of the value. */ hash_reg = (hash_value >> 5) & 0x7F; @@ -3638,7 +3639,7 @@ e1000_rar_set(struct e1000_hw *hw, uint32_t rar_low, rar_high; /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian + * from network order (big endian) to little endian */ rar_low = ((uint32_t) addr[0] | ((uint32_t) addr[1] << 8) | @@ -3764,9 +3765,9 @@ int32_t e1000_setup_led(struct e1000_hw *hw) { uint32_t ledctl; - + DEBUGFUNC("e1000_setup_led"); - + switch(hw->device_id) { case E1000_DEV_ID_82542: case E1000_DEV_ID_82543GC_FIBER: @@ -3784,7 +3785,7 @@ e1000_setup_led(struct e1000_hw *hw) hw->ledctl_default = ledctl; /* Turn off LED0 */ ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | + E1000_LEDCTL_LED0_BLINK | E1000_LEDCTL_LED0_MODE_MASK); ledctl |= (E1000_LEDCTL_MODE_LED_OFF << E1000_LEDCTL_LED0_MODE_SHIFT); E1000_WRITE_REG(hw, LEDCTL, ledctl); @@ -3849,7 +3850,7 @@ e1000_cleanup_led(struct e1000_hw *hw) } return 0; } - + /****************************************************************************** * Turns on the software controllable LED * @@ -3957,7 +3958,7 @@ e1000_led_off(struct e1000_hw *hw) } /****************************************************************************** - * Clears all hardware statistics counters. + * Clears all hardware statistics counters. * * hw - Struct containing variables accessed by shared code *****************************************************************************/ @@ -4076,7 +4077,7 @@ e1000_update_adaptive(struct e1000_hw *hw) DEBUGFUNC("e1000_update_adaptive"); if(hw->adaptive_ifs) { - if((hw->collision_delta * hw->ifs_ratio) > + if((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) { if(hw->tx_packet_delta > MIN_NUM_XMITS) { hw->in_ifs_mode = TRUE; @@ -4089,7 +4090,7 @@ e1000_update_adaptive(struct e1000_hw *hw) } } } else { - if((hw->in_ifs_mode == TRUE) && + if((hw->in_ifs_mode == TRUE) && (hw->tx_packet_delta <= MIN_NUM_XMITS)) { hw->current_ifs_val = 0; hw->in_ifs_mode = FALSE; @@ -4103,7 +4104,7 @@ e1000_update_adaptive(struct e1000_hw *hw) /****************************************************************************** * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT - * + * * hw - Struct containing variables accessed by shared code * frame_len - The length of the frame in question * mac_addr - The Ethernet destination address of the frame in question @@ -4131,16 +4132,16 @@ e1000_tbi_adjust_stats(struct e1000_hw *hw, carry_bit = 0x80000000 & stats->gorcl; stats->gorcl += frame_len; /* If the high bit of Gorcl (the low 32 bits of the Good Octets - * Received Count) was one before the addition, - * AND it is zero after, then we lost the carry out, + * Received Count) was one before the addition, + * AND it is zero after, then we lost the carry out, * need to add one to Gorch (Good Octets Received Count High). - * This could be simplified if all environments supported + * This could be simplified if all environments supported * 64-bit integers. */ if(carry_bit && ((stats->gorcl & 0x80000000) == 0)) stats->gorch++; /* Is this a broadcast or multicast? Check broadcast first, - * since the test for a multicast frame will test positive on + * since the test for a multicast frame will test positive on * a broadcast frame. */ if((mac_addr[0] == (uint8_t) 0xff) && (mac_addr[1] == (uint8_t) 0xff)) diff --git a/drivers/net/e1000/e1000_hw.h b/drivers/net/e1000/e1000_hw.h index 5e1fbab33047..3fe0febaa7e7 100644 --- a/drivers/net/e1000/e1000_hw.h +++ b/drivers/net/e1000/e1000_hw.h @@ -33,6 +33,7 @@ #ifndef _E1000_HW_H_ #define _E1000_HW_H_ + #include "e1000_osdep.h" /* Forward declarations of structures used by the shared code */ @@ -290,6 +291,7 @@ uint32_t e1000_io_read(struct e1000_hw *hw, uint32_t port); uint32_t e1000_read_reg_io(struct e1000_hw *hw, uint32_t offset); void e1000_io_write(struct e1000_hw *hw, uint32_t port, uint32_t value); void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); + #define E1000_READ_REG_IO(a, reg) \ e1000_read_reg_io((a), E1000_##reg) #define E1000_WRITE_REG_IO(a, reg, val) \ @@ -360,7 +362,7 @@ void e1000_write_reg_io(struct e1000_hw *hw, uint32_t offset, uint32_t value); /* This defines the bits that are set in the Interrupt Mask * Set/Read Register. Each bit is documented below: * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error + * o RXSEQ = Receive Sequence Error */ #define POLL_IMS_ENABLE_MASK ( \ E1000_IMS_RXDMT0 | \ @@ -585,7 +587,7 @@ struct e1000_ffvt_entry { /* Register Set. (82543, 82544) * * Registers are defined to be 32 bits and should be accessed as 32 bit values. - * These registers are physically located on the NIC, but are mapped into the + * These registers are physically located on the NIC, but are mapped into the * host memory address space. * * RW - register is both readable and writable @@ -1374,7 +1376,7 @@ struct e1000_hw { #define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */ #define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */ #define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ -#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery +#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery * Filtering */ #define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ #define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ @@ -1555,26 +1557,26 @@ struct e1000_hw { /* The number of bits that we need to shift right to move the "pause" * bits from the EEPROM (bits 13:12) to the "pause" (bits 8:7) field - * in the TXCW register + * in the TXCW register */ #define PAUSE_SHIFT 5 /* The number of bits that we need to shift left to move the "SWDPIO" * bits from the EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field - * in the CTRL register + * in the CTRL register */ #define SWDPIO_SHIFT 17 /* The number of bits that we need to shift left to move the "SWDPIO_EXT" * bits from the EEPROM word F (bits 7:4) to the bits 11:8 of The * Extended CTRL register. - * in the CTRL register + * in the CTRL register */ #define SWDPIO__EXT_SHIFT 4 /* The number of bits that we need to shift left to move the "ILOS" * bit from the EEPROM (bit 4) to the "ILOS" (bit 7) field - * in the CTRL register + * in the CTRL register */ #define ILOS_SHIFT 3 @@ -1592,7 +1594,7 @@ struct e1000_hw { /* TBI_ACCEPT macro definition: * * This macro requires: - * adapter = a pointer to struct e1000_hw + * adapter = a pointer to struct e1000_hw * status = the 8 bit status field of the RX descriptor with EOP set * error = the 8 bit error field of the RX descriptor with EOP set * length = the sum of all the length fields of the RX descriptors that @@ -1601,7 +1603,7 @@ struct e1000_hw { * max_frame_length = the maximum frame length we want to accept. * min_frame_length = the minimum frame length we want to accept. * - * This macro is a conditional that should be used in the interrupt + * This macro is a conditional that should be used in the interrupt * handler's Rx processing routine when RxErrors have been detected. * * Typical use: @@ -1748,7 +1750,7 @@ struct e1000_hw { #define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ #define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ #define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ -#define NWAY_ER_PAR_DETECT_FAULT 0x0100 /* LP is 100TX Full Duplex Capable */ +#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */ /* Next Page TX Register */ #define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ @@ -1759,7 +1761,7 @@ struct e1000_hw { * 0 = cannot comply with msg */ #define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow +#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow * 0 = sending last NP */ @@ -1768,13 +1770,13 @@ struct e1000_hw { #define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges * of different NP */ -#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg +#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg * 0 = cannot comply with msg */ #define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ #define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */ #define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP + * 0 = sending last NP */ /* 1000BASE-T Control Register */ @@ -1821,20 +1823,20 @@ struct e1000_hw { #define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ #define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ #define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ -#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, +#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, * 0=CLK125 toggling */ #define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ /* Manual MDI configuration */ #define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ #define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, - * 100BASE-TX/10BASE-T: + * 100BASE-TX/10BASE-T: * MDI Mode */ -#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled - * all speeds. +#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled + * all speeds. */ -#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 +#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 /* 1=Enable Extended 10BASE-T distance * (Lower 10BASE-T RX Threshold) * 0=Normal 10BASE-T RX Threshold */ @@ -1875,12 +1877,12 @@ struct e1000_hw { #define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 /* 1=Lost lock detect enabled. * Will assert lost lock and bring * link down if idle not seen - * within 1ms in 1000BASE-T + * within 1ms in 1000BASE-T */ /* Number of times we will attempt to autonegotiate before downshifting if we * are the master */ #define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 +#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800 #define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00 diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index cee1eabe9c25..1cfc0c6c08d8 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -189,6 +189,7 @@ struct notifier_block e1000_notifier_reboot = { .priority = 0 }; + /* Exported from other modules */ extern void e1000_check_options(struct e1000_adapter *adapter); @@ -554,6 +555,7 @@ e1000_remove(struct pci_dev *pdev) e1000_phy_hw_reset(&adapter->hw); + iounmap(adapter->hw.hw_addr); pci_release_regions(pdev); @@ -589,7 +591,7 @@ e1000_sw_init(struct e1000_adapter *adapter) adapter->rx_buffer_len = E1000_RXBUFFER_2048; hw->max_frame_size = netdev->mtu + - ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; /* identify the MAC */ @@ -810,7 +812,7 @@ e1000_configure_tx(struct e1000_adapter *adapter) tctl &= ~E1000_TCTL_CT; tctl |= E1000_TCTL_EN | E1000_TCTL_PSP | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); + (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); E1000_WRITE_REG(&adapter->hw, TCTL, tctl); @@ -880,8 +882,8 @@ e1000_setup_rctl(struct e1000_adapter *adapter) rctl &= ~(3 << E1000_RCTL_MO_SHIFT); rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | - E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | - (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT); + E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | + (adapter->hw.mc_filter_type << E1000_RCTL_MO_SHIFT); if(adapter->hw.tbi_compatibility_on == 1) rctl |= E1000_RCTL_SBP; @@ -1374,7 +1376,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags) int i; uint8_t ipcss, ipcso, tucss, tucso, hdr_len; uint16_t ipcse, tucse, mss; - + if(skb_shinfo(skb)->tso_size) { hdr_len = ((skb->h.raw - skb->data) + (skb->h.th->doff << 2)); mss = skb_shinfo(skb)->tso_size; @@ -1394,7 +1396,7 @@ e1000_tso(struct e1000_adapter *adapter, struct sk_buff *skb, int tx_flags) i = adapter->tx_ring.next_to_use; context_desc = E1000_CONTEXT_DESC(adapter->tx_ring, i); - + context_desc->lower_setup.ip_fields.ipcss = ipcss; context_desc->lower_setup.ip_fields.ipcso = ipcso; context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); @@ -2535,6 +2537,7 @@ e1000_notify_reboot(struct notifier_block *nb, unsigned long event, void *p) return NOTIFY_DONE; } + static int e1000_suspend(struct pci_dev *pdev, uint32_t state) { diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index bf5ac6b9e7f6..5e321fc70507 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -169,7 +169,7 @@ E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); * * Valid Range: 0-65535 * - * Default Value: 0/128 + * Default Value: 0 */ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); @@ -309,7 +309,7 @@ e1000_check_options(struct e1000_adapter *adapter) .name = "Transmit Descriptors", .err = "using default of " __MODULE_STRING(DEFAULT_TXD), .def = DEFAULT_TXD, - .arg = { .r = { .min = MIN_TXD }} + .arg = { .r { .min = MIN_TXD }} }; struct e1000_desc_ring *tx_ring = &adapter->tx_ring; e1000_mac_type mac_type = adapter->hw.mac_type; @@ -362,7 +362,8 @@ e1000_check_options(struct e1000_adapter *adapter) .name = "Flow Control", .err = "reading default settings from EEPROM", .def = e1000_fc_default, - .arg = { .l = { .nr = ARRAY_SIZE(fc_list), .p = fc_list }} + .arg = { .l = { .nr = ARRAY_SIZE(fc_list), + .p = fc_list }} }; int fc = FlowControl[bd]; @@ -370,58 +371,57 @@ e1000_check_options(struct e1000_adapter *adapter) adapter->hw.fc = adapter->hw.original_fc = fc; } { /* Transmit Interrupt Delay */ - char *tidv = "using default of " __MODULE_STRING(DEFAULT_TIDV); struct e1000_option opt = { .type = range_option, .name = "Transmit Interrupt Delay", - .arg = { .r = { .min = MIN_TXDELAY, .max = MAX_TXDELAY }} + .err = "using default of " __MODULE_STRING(DEFAULT_TIDV), + .def = DEFAULT_TIDV, + .arg = { .r = { .min = MIN_TXDELAY, + .max = MAX_TXDELAY }} }; - opt.def = DEFAULT_TIDV; - opt.err = tidv; adapter->tx_int_delay = TxIntDelay[bd]; e1000_validate_option(&adapter->tx_int_delay, &opt); } { /* Transmit Absolute Interrupt Delay */ - char *tadv = "using default of " __MODULE_STRING(DEFAULT_TADV); struct e1000_option opt = { .type = range_option, .name = "Transmit Absolute Interrupt Delay", - .arg = { .r = { .min = MIN_TXABSDELAY, .max = MAX_TXABSDELAY }} + .err = "using default of " __MODULE_STRING(DEFAULT_TADV), + .def = DEFAULT_TADV, + .arg = { .r = { .min = MIN_TXABSDELAY, + .max = MAX_TXABSDELAY }} }; - opt.def = DEFAULT_TADV; - opt.err = tadv; adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; e1000_validate_option(&adapter->tx_abs_int_delay, &opt); } { /* Receive Interrupt Delay */ - char *rdtr = "using default of " __MODULE_STRING(DEFAULT_RDTR); struct e1000_option opt = { .type = range_option, .name = "Receive Interrupt Delay", - .arg = { .r = { .min = MIN_RXDELAY, .max = MAX_RXDELAY }} + .err = "using default of " __MODULE_STRING(DEFAULT_RDTR), + .def = DEFAULT_RDTR, + .arg = { .r = { .min = MIN_RXDELAY, + .max = MAX_RXDELAY }} }; - opt.def = DEFAULT_RDTR; - opt.err = rdtr; adapter->rx_int_delay = RxIntDelay[bd]; e1000_validate_option(&adapter->rx_int_delay, &opt); } { /* Receive Absolute Interrupt Delay */ - char *radv = "using default of " __MODULE_STRING(DEFAULT_RADV); struct e1000_option opt = { .type = range_option, .name = "Receive Absolute Interrupt Delay", - .arg = { .r = { .min = MIN_RXABSDELAY, .max = MAX_RXABSDELAY }} + .err = "using default of " __MODULE_STRING(DEFAULT_RADV), + .def = DEFAULT_RADV, + .arg = { .r = { .min = MIN_RXABSDELAY, + .max = MAX_RXABSDELAY }} }; - opt.def = DEFAULT_RADV; - opt.err = radv; adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; e1000_validate_option(&adapter->rx_abs_int_delay, &opt); } - switch(adapter->hw.media_type) { case e1000_media_type_fiber: e1000_check_fiber_options(adapter); @@ -486,7 +486,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) .name = "Speed", .err = "parameter ignored", .def = 0, - .arg = { .l = { .nr = ARRAY_SIZE(speed_list), .p = speed_list }} + .arg = { .l = { .nr = ARRAY_SIZE(speed_list), + .p = speed_list }} }; speed = Speed[bd]; @@ -502,7 +503,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) .name = "Duplex", .err = "parameter ignored", .def = 0, - .arg = { .l = { .nr = ARRAY_SIZE(dplx_list), .p = dplx_list }} + .arg = { .l = { .nr = ARRAY_SIZE(dplx_list), + .p = dplx_list }} }; dplx = Duplex[bd]; @@ -554,7 +556,8 @@ e1000_check_copper_options(struct e1000_adapter *adapter) .name = "AutoNeg", .err = "parameter ignored", .def = AUTONEG_ADV_DEFAULT, - .arg = { .l = { .nr = ARRAY_SIZE(an_list), .p = an_list }} + .arg = { .l = { .nr = ARRAY_SIZE(an_list), + .p = an_list }} }; int an = AutoNeg[bd]; -- cgit v1.2.3 From 5a14251f54bad266c11ed1afd8b74f3ff1eefb49 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:44:29 -0500 Subject: [E1000] Added Tx FIFO flush routine * Added method to flush Tx FIFO after link disconnect; the hardware hangs on to Tx skb's that were in flight prior to link loss --- drivers/net/e1000/e1000_main.c | 43 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 1cfc0c6c08d8..f55085b0611e 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -1246,6 +1246,40 @@ e1000_set_multi(struct net_device *netdev) e1000_leave_82542_rst(adapter); } +static void +e1000_tx_flush(struct e1000_adapter *adapter) +{ + uint32_t ctrl, tctl, txcw, icr; + + e1000_irq_disable(adapter); + + if(adapter->hw.mac_type < e1000_82543) { + /* Transmit Unit Reset */ + tctl = E1000_READ_REG(&adapter->hw, TCTL); + E1000_WRITE_REG(&adapter->hw, TCTL, tctl | E1000_TCTL_RST); + E1000_WRITE_REG(&adapter->hw, TCTL, tctl); + e1000_clean_tx_ring(adapter); + e1000_configure_tx(adapter); + } else { + txcw = E1000_READ_REG(&adapter->hw, TXCW); + E1000_WRITE_REG(&adapter->hw, TXCW, txcw & ~E1000_TXCW_ANE); + + ctrl = E1000_READ_REG(&adapter->hw, CTRL); + E1000_WRITE_REG(&adapter->hw, CTRL, ctrl | E1000_CTRL_SLU | + E1000_CTRL_ILOS); + + mdelay(10); + + e1000_clean_tx_irq(adapter); + E1000_WRITE_REG(&adapter->hw, CTRL, ctrl); + E1000_WRITE_REG(&adapter->hw, TXCW, txcw); + + /* clear the link status change interrupts this caused */ + icr = E1000_READ_REG(&adapter->hw, ICR); + } + + e1000_irq_enable(adapter); +} /* need to wait a few seconds after link up to get diagnostic information from the phy */ @@ -1348,6 +1382,15 @@ e1000_watchdog(unsigned long data) e1000_update_stats(adapter); e1000_update_adaptive(&adapter->hw); + if(!netif_carrier_ok(netdev)) { + if(E1000_DESC_UNUSED(txdr) + 1 < txdr->count) { + unsigned long flags; + spin_lock_irqsave(&netdev->xmit_lock, flags); + e1000_tx_flush(adapter); + spin_unlock_irqrestore(&netdev->xmit_lock, flags); + } + } + /* Cause software interrupt to ensure rx ring is cleaned */ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); -- cgit v1.2.3 From f1caa8c7897d2536028dbb103e59daff3b18c1ea Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:44:54 -0500 Subject: [E1000] Added Interrupt Throttle Rate tuning support * Added Interrupt Throttle Rate tuning support --- Documentation/networking/e1000.txt | 14 ++++++++++++++ drivers/net/e1000/e1000.h | 5 +++++ drivers/net/e1000/e1000_main.c | 27 +++++++++++++++++++-------- drivers/net/e1000/e1000_param.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/Documentation/networking/e1000.txt b/Documentation/networking/e1000.txt index 0d019873fbd5..9b2329f99333 100644 --- a/Documentation/networking/e1000.txt +++ b/Documentation/networking/e1000.txt @@ -123,6 +123,20 @@ Default: Read flow control settings from the EEPROM This parameter controls the automatic generation(Tx) and response(Rx) to Ethernet PAUSE frames. +InterruptThrottleRate +Valid Range: 100-100000 (0=off, 1=dynamic) +Default Value: 1 + This value represents the maximum number of interrupts per second the + controller generates. InterruptThrottleRate is another setting used in + interrupt moderation. Dynamic mode uses a heuristic algorithm to adjust + InterruptThrottleRate based on the current traffic load. + + NOTE: InterruptThrottleRate takes precedence over the TxAbsIntDelay and + RxAbsIntDelay parameters. In other words, minimizing the receive + and/or transmit absolute delays does not force the controller to + generate more interrupts than what the Interrupt Throttle Rate + allows. + RxDescriptors Valid Range: 80-256 for 82542 and 82543-based adapters 80-4096 for 82540, 82544, 82545, and 82546-based adapters diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h index 1c3ae0c55fb3..2b81e45e641f 100644 --- a/drivers/net/e1000/e1000.h +++ b/drivers/net/e1000/e1000.h @@ -187,6 +187,7 @@ struct e1000_adapter { uint32_t txd_cmd; uint32_t tx_int_delay; uint32_t tx_abs_int_delay; + uint32_t gotcl; uint32_t tx_fifo_head; uint32_t tx_head_addr; uint32_t tx_fifo_size; @@ -199,6 +200,10 @@ struct e1000_adapter { uint32_t rx_int_delay; uint32_t rx_abs_int_delay; boolean_t rx_csum; + uint32_t gorcl; + + /* Interrupt Throttle Rate */ + uint32_t itr; /* OS defined structs */ struct net_device *netdev; diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index f55085b0611e..34590cec3cdd 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -937,12 +937,9 @@ e1000_configure_rx(struct e1000_adapter *adapter) if(adapter->hw.mac_type >= e1000_82540) { E1000_WRITE_REG(&adapter->hw, RADV, adapter->rx_abs_int_delay); - - /* Set the interrupt throttling rate. Value is calculated - * as DEFAULT_ITR = 1/(MAX_INTS_PER_SEC * 256ns) */ -#define MAX_INTS_PER_SEC 8000 -#define DEFAULT_ITR 1000000000/(MAX_INTS_PER_SEC * 256) - E1000_WRITE_REG(&adapter->hw, ITR, DEFAULT_ITR); + if(adapter->itr > 1) + E1000_WRITE_REG(&adapter->hw, ITR, + 1000000000 / (adapter->itr * 256)); } /* Setup the Base and Length of the Rx Descriptor Ring */ @@ -1391,6 +1388,18 @@ e1000_watchdog(unsigned long data) } } + /* Dynamic mode for Interrupt Throttle Rate (ITR) */ + if(adapter->hw.mac_type >= e1000_82540 && adapter->itr == 1) { + /* Symmetric Tx/Rx gets a reduced ITR=2000; Total + * asymmetrical Tx or Rx gets ITR=8000; everyone + * else is between 2000-8000. */ + uint32_t goc = (adapter->gotcl + adapter->gorcl) / 10000; + uint32_t dif = (adapter->gotcl > adapter->gorcl ? + adapter->gotcl - adapter->gorcl : + adapter->gorcl - adapter->gotcl) / 10000; + uint32_t itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; + E1000_WRITE_REG(&adapter->hw, ITR, 1000000000 / (itr * 256)); + } /* Cause software interrupt to ensure rx ring is cleaned */ E1000_WRITE_REG(&adapter->hw, ICS, E1000_ICS_RXDMT0); @@ -1811,7 +1820,8 @@ e1000_update_stats(struct e1000_adapter *adapter) adapter->stats.crcerrs += E1000_READ_REG(hw, CRCERRS); adapter->stats.gprc += E1000_READ_REG(hw, GPRC); - adapter->stats.gorcl += E1000_READ_REG(hw, GORCL); + adapter->gorcl = E1000_READ_REG(hw, GORCL); + adapter->stats.gorcl += adapter->gorcl; adapter->stats.gorch += E1000_READ_REG(hw, GORCH); adapter->stats.bprc += E1000_READ_REG(hw, BPRC); adapter->stats.mprc += E1000_READ_REG(hw, MPRC); @@ -1842,7 +1852,8 @@ e1000_update_stats(struct e1000_adapter *adapter) adapter->stats.xofftxc += E1000_READ_REG(hw, XOFFTXC); adapter->stats.fcruc += E1000_READ_REG(hw, FCRUC); adapter->stats.gptc += E1000_READ_REG(hw, GPTC); - adapter->stats.gotcl += E1000_READ_REG(hw, GOTCL); + adapter->gotcl = E1000_READ_REG(hw, GOTCL); + adapter->stats.gotcl += adapter->gotcl; adapter->stats.gotch += E1000_READ_REG(hw, GOTCH); adapter->stats.rnbc += E1000_READ_REG(hw, RNBC); adapter->stats.ruc += E1000_READ_REG(hw, RUC); diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index 5e321fc70507..75a50ff6f42e 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -183,6 +183,15 @@ E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); +/* Interrupt Throttle Rate (interrupts/sec) + * + * Valid Range: 100-100000 (0=off, 1=dynamic) + * + * Default Value: 1 + */ + +E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); + #define AUTONEG_ADV_DEFAULT 0x2F #define AUTONEG_ADV_MASK 0x2F #define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL @@ -213,6 +222,10 @@ E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); #define MAX_TXABSDELAY 0xFFFF #define MIN_TXABSDELAY 0 +#define DEFAULT_ITR 1 +#define MAX_ITR 100000 +#define MIN_ITR 100 + struct e1000_option { enum { enable_option, range_option, list_option } type; char *name; @@ -422,6 +435,27 @@ e1000_check_options(struct e1000_adapter *adapter) adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; e1000_validate_option(&adapter->rx_abs_int_delay, &opt); } + { /* Interrupt Throttling Rate */ + struct e1000_option opt = { + .type = range_option, + .name = "Interrupt Throttling Rate (ints/sec)", + .err = "using default of " __MODULE_STRING(DEFAULT_ITR), + .def = DEFAULT_ITR, + .arg = { .r = { .min = MIN_ITR, + .max = MAX_ITR }} + }; + + adapter->itr = InterruptThrottleRate[bd]; + if(adapter->itr == 0) { + printk(KERN_INFO "%s turned off\n", opt.name); + } else if(adapter->itr == 1 || adapter->itr == -1) { + /* Dynamic mode */ + adapter->itr = 1; + } else { + e1000_validate_option(&adapter->itr, &opt); + } + } + switch(adapter->hw.media_type) { case e1000_media_type_fiber: e1000_check_fiber_options(adapter); -- cgit v1.2.3 From d2c2518b116dc9611957c14f58f5ef70b510e134 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:45:19 -0500 Subject: [E1000] Controller wake-up thru ASF fix * Fixed controller wake-up through ASF --- drivers/net/e1000/e1000_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 34590cec3cdd..5b14cd644cfd 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -2656,7 +2656,8 @@ e1000_suspend(struct pci_dev *pdev, uint32_t state) if(manc & E1000_MANC_SMBUS_EN) { manc |= E1000_MANC_ARP_EN; E1000_WRITE_REG(&adapter->hw, MANC, manc); - state = 0; + pci_enable_wake(pdev, 3, 1); + pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */ } } -- cgit v1.2.3 From 6938f0a035dd383a6198d663b3951b16cbf1fed0 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:45:43 -0500 Subject: [E1000] whitespace fix from previous patches * Corrected indentation from previous patches --- drivers/net/e1000/e1000_hw.c | 414 ++++++++++++++++++++++--------------------- 1 file changed, 209 insertions(+), 205 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_hw.c b/drivers/net/e1000/e1000_hw.c index 193bfe98f0ed..3527e7794635 100644 --- a/drivers/net/e1000/e1000_hw.c +++ b/drivers/net/e1000/e1000_hw.c @@ -718,143 +718,147 @@ e1000_setup_copper_link(struct e1000_hw *hw) } DEBUGOUT1("Phy ID = %x \n", hw->phy_id); -if (hw->phy_type == e1000_phy_igp) { + if (hw->phy_type == e1000_phy_igp) { - ret_val = e1000_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; - } + ret_val = e1000_phy_reset(hw); + if(ret_val < 0) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } - /* Wait 10ms for MAC to configure PHY from eeprom settings */ - msec_delay(15); + /* Wait 10ms for MAC to configure PHY from eeprom settings */ + msec_delay(15); - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0000) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + + /* Configure activity LED after PHY reset */ + led_ctrl = E1000_READ_REG(hw, LEDCTL); + led_ctrl &= IGP_ACTIVITY_LED_MASK; + led_ctrl |= IGP_ACTIVITY_LED_ENABLE; + if(hw->mac_type == e1000_82547) + led_ctrl |= IGP_LED3_MODE; + E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - /* Configure activity LED after PHY reset */ - led_ctrl = E1000_READ_REG(hw, LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= IGP_ACTIVITY_LED_ENABLE; - if(hw->mac_type == e1000_82547) - led_ctrl |= IGP_LED3_MODE; - E1000_WRITE_REG(hw, LEDCTL, led_ctrl); - - if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, &phy_data) < 0) { + if(hw->autoneg_advertised == ADVERTISE_1000_FULL) { + /* Disable SmartSpeed */ + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, + phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + /* Set auto Master/Slave resolution process */ + if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data &= ~CR_1000T_MS_ENABLE; + if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + } + + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, phy_data) < 0) { + + /* Force MDI for IGP PHY */ + phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | + IGP01E1000_PSCR_FORCE_MDI_MDIX); + + hw->mdix = 1; + + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { DEBUGOUT("PHY Write Error\n"); return -E1000_ERR_PHY; } - /* Set auto Master/Slave resolution process */ - if(e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data) < 0) { + + } else { + /* Enable CRS on TX. This must be set for half-duplex operation. */ + if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } - phy_data &= ~CR_1000T_MS_ENABLE; - if(e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data) < 0) { + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + + /* Options: + * MDI/MDI-X = 0 (default) + * 0 - Auto for all speeds + * 1 - MDI mode + * 2 - MDI-X mode + * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + + switch (hw->mdix) { + case 1: + phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; + break; + case 2: + phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; + break; + case 3: + phy_data |= M88E1000_PSCR_AUTO_X_1000T; + break; + case 0: + default: + phy_data |= M88E1000_PSCR_AUTO_X_MODE; + break; + } + + /* Options: + * disable_polarity_correction = 0 (default) + * Automatic Correction for Reversed Cable Polarity + * 0 - Disabled + * 1 - Enabled + */ + phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; + if(hw->disable_polarity_correction == 1) + phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; + if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { DEBUGOUT("PHY Write Error\n"); return -E1000_ERR_PHY; } - } - - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - - /* Force MDI for IGP PHY */ - phy_data &= ~(IGP01E1000_PSCR_AUTO_MDIX | IGP01E1000_PSCR_FORCE_MDI_MDIX); - - hw->mdix = 1; - - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - -} else { - /* Enable CRS on TX. This must be set for half-duplex operation. */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (hw->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if(hw->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); + /* Force TX_CLK in the Extended PHY Specific Control Register + * to 25MHz clock. + */ + if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); return -E1000_ERR_PHY; } - } + phy_data |= M88E1000_EPSCR_TX_CLK_25; + + if (hw->phy_revision < M88E1011_I_REV_4) { + /* Configure Master and Slave downshift values */ + phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); + phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | + M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); + if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, + phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + } - /* SW Reset the PHY so all changes take effect */ - ret_val = e1000_phy_reset(hw); - if(ret_val < 0) { - DEBUGOUT("Error Resetting the PHY\n"); - return ret_val; + /* SW Reset the PHY so all changes take effect */ + ret_val = e1000_phy_reset(hw); + if(ret_val < 0) { + DEBUGOUT("Error Resetting the PHY\n"); + return ret_val; + } } -} /* Options: * autoneg = 1 (default) @@ -1193,41 +1197,41 @@ e1000_phy_force_speed_duplex(struct e1000_hw *hw) /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); -if (hw->phy_type == e1000_phy_m88) { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + if (hw->phy_type == e1000_phy_m88) { + if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } - /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed are duplex are forced. - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } - DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data); + /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI + * forced whenever speed are duplex are forced. + */ + phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; + if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } + DEBUGOUT1("M88E1000 PSCR: %x \n", phy_data); - /* Need to reset the PHY or these changes will be ignored */ - mii_ctrl_reg |= MII_CR_RESET; -} else { - /* Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed or duplex are forced. - */ - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } + /* Need to reset the PHY or these changes will be ignored */ + mii_ctrl_reg |= MII_CR_RESET; + } else { + /* Clear Auto-Crossover to force MDI manually. IGP requires MDI + * forced whenever speed or duplex are forced. + */ + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; + phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; + phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + if(e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } } -} /* Write back the modified PHY MII control register. */ if(e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg) < 0) { @@ -1291,34 +1295,34 @@ if (hw->phy_type == e1000_phy_m88) { } } -if (hw->phy_type == e1000_phy_m88) { - /* Because we reset the PHY above, we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock. This value - * defaults back to a 2.5MHz clock when the PHY is reset. - */ - if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_EPSCR_TX_CLK_25; - if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; - } + if (hw->phy_type == e1000_phy_m88) { + /* Because we reset the PHY above, we need to re-force TX_CLK in the + * Extended PHY Specific Control Register to 25MHz clock. This value + * defaults back to a 2.5MHz clock when the PHY is reset. + */ + if(e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data |= M88E1000_EPSCR_TX_CLK_25; + if(e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } - /* In addition, because of the s/w reset above, we need to enable CRS on - * TX. This must be set for both full and half duplex operation. - */ - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { - DEBUGOUT("PHY Write Error\n"); - return -E1000_ERR_PHY; + /* In addition, because of the s/w reset above, we need to enable CRS on + * TX. This must be set for both full and half duplex operation. + */ + if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; + if(e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data) < 0) { + DEBUGOUT("PHY Write Error\n"); + return -E1000_ERR_PHY; + } } -} return 0; } @@ -1373,43 +1377,43 @@ e1000_config_mac_to_phy(struct e1000_hw *hw) /* Set up duplex in the Device Control and Transmit Control * registers depending on negotiated values. */ -if (hw->phy_type == e1000_phy_igp) { - if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; - else ctrl &= ~E1000_CTRL_FD; + if (hw->phy_type == e1000_phy_igp) { + if(e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + if(phy_data & IGP01E1000_PSSR_FULL_DUPLEX) ctrl |= E1000_CTRL_FD; + else ctrl &= ~E1000_CTRL_FD; - e1000_config_collision_dist(hw); + e1000_config_collision_dist(hw); - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) - ctrl |= E1000_CTRL_SPD_1000; - else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_100MBPS) - ctrl |= E1000_CTRL_SPD_100; -} else { - if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { - DEBUGOUT("PHY Read Error\n"); - return -E1000_ERR_PHY; - } - if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; - else ctrl &= ~E1000_CTRL_FD; + /* Set up speed in the Device Control register depending on + * negotiated values. + */ + if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_1000MBPS) + ctrl |= E1000_CTRL_SPD_1000; + else if((phy_data & IGP01E1000_PSSR_SPEED_MASK) == + IGP01E1000_PSSR_SPEED_100MBPS) + ctrl |= E1000_CTRL_SPD_100; + } else { + if(e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data) < 0) { + DEBUGOUT("PHY Read Error\n"); + return -E1000_ERR_PHY; + } + if(phy_data & M88E1000_PSSR_DPLX) ctrl |= E1000_CTRL_FD; + else ctrl &= ~E1000_CTRL_FD; - e1000_config_collision_dist(hw); + e1000_config_collision_dist(hw); - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) - ctrl |= E1000_CTRL_SPD_1000; - else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) - ctrl |= E1000_CTRL_SPD_100; -} + /* Set up speed in the Device Control register depending on + * negotiated values. + */ + if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) + ctrl |= E1000_CTRL_SPD_1000; + else if((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) + ctrl |= E1000_CTRL_SPD_100; + } /* Write the configured values back to the Device Control Reg. */ E1000_WRITE_REG(hw, CTRL, ctrl); return 0; -- cgit v1.2.3 From 3cddbbc646bdc9533aaa294c63ff243cf31b8f23 Mon Sep 17 00:00:00 2001 From: "Jeb J. Cramer" Date: Thu, 20 Mar 2003 13:46:10 -0500 Subject: [E1000] NAPI re-insertion w/ changes * Previous patch wiped NAPI support, adding it back here. But, with a twist: this one doesn't disable/enable interrupts each time we enter/leave polling. (It's EXPERIMENTAL). --- drivers/net/e1000/e1000_main.c | 70 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 5b14cd644cfd..10a831f3bbbd 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c @@ -155,8 +155,14 @@ static void e1000_update_stats(struct e1000_adapter *adapter); static inline void e1000_irq_disable(struct e1000_adapter *adapter); static inline void e1000_irq_enable(struct e1000_adapter *adapter); static void e1000_intr(int irq, void *data, struct pt_regs *regs); -static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); +#ifdef CONFIG_E1000_NAPI +static int e1000_clean(struct net_device *netdev, int *budget); +static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter, + int *work_done, int work_to_do); +#else static boolean_t e1000_clean_rx_irq(struct e1000_adapter *adapter); +#endif +static boolean_t e1000_clean_tx_irq(struct e1000_adapter *adapter); static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter); static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, @@ -418,6 +424,10 @@ e1000_probe(struct pci_dev *pdev, netdev->do_ioctl = &e1000_ioctl; netdev->tx_timeout = &e1000_tx_timeout; netdev->watchdog_timeo = 5 * HZ; +#ifdef CONFIG_E1000_NAPI + netdev->poll = &e1000_clean; + netdev->weight = 64; +#endif netdev->vlan_rx_register = e1000_vlan_rx_register; netdev->vlan_rx_add_vid = e1000_vlan_rx_add_vid; netdev->vlan_rx_kill_vid = e1000_vlan_rx_kill_vid; @@ -1977,7 +1987,9 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) struct net_device *netdev = data; struct e1000_adapter *adapter = netdev->priv; uint32_t icr = E1000_READ_REG(&adapter->hw, ICR); +#ifndef CONFIG_E1000_NAPI int i; +#endif if(!icr) return; /* Not our interrupt */ @@ -1987,12 +1999,46 @@ e1000_intr(int irq, void *data, struct pt_regs *regs) mod_timer(&adapter->watchdog_timer, jiffies); } +#ifdef CONFIG_E1000_NAPI + /* Don't disable interrupts - rely on h/w interrupt + * moderation to keep interrupts low. netif_rx_schedule + * is NOP if already polling. */ + netif_rx_schedule(netdev); +#else for(i = 0; i < E1000_MAX_INTR; i++) if(!e1000_clean_rx_irq(adapter) && !e1000_clean_tx_irq(adapter)) break; +#endif +} +#ifdef CONFIG_E1000_NAPI +/** + * e1000_clean - NAPI Rx polling callback + * @adapter: board private structure + **/ + +static int +e1000_clean(struct net_device *netdev, int *budget) +{ + struct e1000_adapter *adapter = netdev->priv; + int work_to_do = min(*budget, netdev->quota); + int work_done = 0; + + while(work_done < work_to_do) + if(!e1000_clean_rx_irq(adapter, &work_done, work_to_do) && + !e1000_clean_tx_irq(adapter)) + break; + + *budget -= work_done; + netdev->quota -= work_done; + + if(work_done < work_to_do) + netif_rx_complete(netdev); + + return (work_done >= work_to_do); } +#endif /** * e1000_clean_tx_irq - Reclaim resources after transmit completes @@ -2054,7 +2100,12 @@ e1000_clean_tx_irq(struct e1000_adapter *adapter) **/ static boolean_t +#ifdef CONFIG_E1000_NAPI +e1000_clean_rx_irq(struct e1000_adapter *adapter, int *work_done, + int work_to_do) +#else e1000_clean_rx_irq(struct e1000_adapter *adapter) +#endif { struct e1000_desc_ring *rx_ring = &adapter->rx_ring; struct net_device *netdev = adapter->netdev; @@ -2071,6 +2122,13 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) while(rx_desc->status & E1000_RXD_STAT_DD) { +#ifdef CONFIG_E1000_NAPI + if(*work_done >= work_to_do) + break; + + (*work_done)++; +#endif + cleaned = TRUE; pci_unmap_single(pdev, @@ -2133,12 +2191,22 @@ e1000_clean_rx_irq(struct e1000_adapter *adapter) e1000_rx_checksum(adapter, rx_desc, skb); skb->protocol = eth_type_trans(skb, netdev); +#ifdef CONFIG_E1000_NAPI + if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { + vlan_hwaccel_receive_skb(skb, adapter->vlgrp, + (rx_desc->special & E1000_RXD_SPC_VLAN_MASK)); + } else { + netif_receive_skb(skb); + } +#else /* CONFIG_E1000_NAPI */ if(adapter->vlgrp && (rx_desc->status & E1000_RXD_STAT_VP)) { vlan_hwaccel_rx(skb, adapter->vlgrp, (rx_desc->special & E1000_RXD_SPC_VLAN_MASK)); } else { netif_rx(skb); } +#endif /* CONFIG_E1000_NAPI */ + netdev->last_rx = jiffies; rx_desc->status = 0; -- cgit v1.2.3 From 0e6cb0bc3acbe4e2388f63f8cfe41e8075062de0 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 20 Mar 2003 14:01:37 -0500 Subject: [netdrvr tg3] fix memleak in DMA test Also, bump version to 1.5. Leak fix contributed by Don Fry @ IBM --- drivers/net/tg3.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 8f48359a3496..ea4082646fde 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -55,8 +55,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4c" -#define DRV_MODULE_RELDATE "Feb 18, 2003" +#define DRV_MODULE_VERSION "1.5" +#define DRV_MODULE_RELDATE "March 21, 2003" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -6581,11 +6581,11 @@ static int __devinit tg3_test_dma(struct tg3 *tp) tw32(TG3PCI_DMA_RW_CTRL, tp->dma_rwctrl); + ret = 0; if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 && GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) - return 0; + goto out; - ret = 0; while (1) { u32 *p, i; -- cgit v1.2.3 From eb0e2cf6acb7e2ac9afa684b42620e8036f5c47f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 20 Mar 2003 05:47:56 -0800 Subject: [PATCH] Add missing put_user checks in n_tty From: Steven Rostedt The n_tty driver is missing some put_user checks. --- drivers/char/n_tty.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index c80d79a80bd0..d4991bac9437 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -1029,7 +1029,10 @@ do_it_again: break; cs = tty->link->ctrl_status; tty->link->ctrl_status = 0; - put_user(cs, b++); + if (put_user(cs, b++)) { + retval = -EFAULT; + break; + } nr--; break; } @@ -1068,7 +1071,10 @@ do_it_again: /* Deal with packet mode. */ if (tty->packet && b == buf) { - put_user(TIOCPKT_DATA, b++); + if (put_user(TIOCPKT_DATA, b++)) { + retval = -EFAULT; + break; + } nr--; } @@ -1095,12 +1101,17 @@ do_it_again: spin_unlock_irqrestore(&tty->read_lock, flags); if (!eol || (c != __DISABLED_CHAR)) { - put_user(c, b++); + if (put_user(c, b++)) { + retval = -EFAULT; + break; + } nr--; } if (eol) break; } + if (retval) + break; } else { int uncopied; uncopied = copy_from_read_buf(tty, &b, &nr); @@ -1135,7 +1146,7 @@ do_it_again: current->state = TASK_RUNNING; size = b - buf; - if (size) { + if (!retval && size) { retval = size; if (nr) clear_bit(TTY_PUSH, &tty->flags); -- cgit v1.2.3 From 9e0acd29bdcaf3254d438f86e33c89c08c37b5bf Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 20 Mar 2003 05:48:10 -0800 Subject: [PATCH] raw driver: rewrite i_mapping only on final close The recent fix to the raw driver wasn't quite right: it rewrites the character-special inode's i_mapping to point back to itself on each close. So any other currently-open handles against /dev/raw/rawN get a nasty surprise. Change it to only rewrite i_mapping on the final close. Also, change it so that it only redirects its i_mapping on the initial open. This is not necessary, but is neater. --- drivers/char/raw.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/char/raw.c b/drivers/char/raw.c index ac5f3c0f6041..537b95ba2275 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -70,10 +70,10 @@ static int raw_open(struct inode *inode, struct file *filp) } else { err = set_blocksize(bdev, bdev_hardsect_size(bdev)); if (err == 0) { - raw_devices[minor].inuse++; - filp->f_dentry->d_inode->i_mapping = - bdev->bd_inode->i_mapping; filp->f_flags |= O_DIRECT; + if (++raw_devices[minor].inuse == 1) + filp->f_dentry->d_inode->i_mapping = + bdev->bd_inode->i_mapping; } } } @@ -83,6 +83,10 @@ out: return err; } +/* + * When the final fd which refers to this character-special node is closed, we + * make its ->mapping point back at its own i_data. + */ static int raw_release(struct inode *inode, struct file *filp) { const int minor= minor(inode->i_rdev); @@ -90,12 +94,12 @@ static int raw_release(struct inode *inode, struct file *filp) down(&raw_mutex); bdev = raw_devices[minor].binding; - raw_devices[minor].inuse--; + if (--raw_devices[minor].inuse == 0) { + /* Here inode->i_mapping == bdev->bd_inode->i_mapping */ + inode->i_mapping = &inode->i_data; + inode->i_mapping->backing_dev_info = &default_backing_dev_info; + } up(&raw_mutex); - - /* Here inode->i_mapping == bdev->bd_inode->i_mapping */ - inode->i_mapping = &inode->i_data; - inode->i_mapping->backing_dev_info = &default_backing_dev_info; bd_release(bdev); blkdev_put(bdev, BDEV_RAW); -- cgit v1.2.3 From 3abd0aeaeda40861c40054a6d988bd9c1d9b1b44 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 20 Mar 2003 05:48:18 -0800 Subject: [PATCH] raw driver: cleanups and small fixes - There was an unchecked bdget(). bdget can fail due to ENOMEM. - rework the error handling implementation in raw_ctl_ioctl(). - Replace MOD_INC_USE_COUNT with try_module_get(THIS_MODULE). This allows the raw module to be unloaded again. The core kernel has already taken a ref on the module prior to entering the ioctl, so try_module_get() cannot fail. --- drivers/char/raw.c | 53 +++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 537b95ba2275..08fd00d4fce4 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c @@ -50,7 +50,7 @@ static int raw_open(struct inode *inode, struct file *filp) filp->f_op = &raw_ctl_fops; return 0; } - + down(&raw_mutex); /* @@ -100,7 +100,7 @@ static int raw_release(struct inode *inode, struct file *filp) inode->i_mapping->backing_dev_info = &default_backing_dev_info; } up(&raw_mutex); - + bd_release(bdev); blkdev_put(bdev, BDEV_RAW); return 0; @@ -122,27 +122,28 @@ raw_ioctl(struct inode *inode, struct file *filp, * Deal with ioctls against the raw-device control interface, to bind * and unbind other raw devices. */ -static int -raw_ctl_ioctl(struct inode *inode, struct file *filp, - unsigned int command, unsigned long arg) +static int raw_ctl_ioctl(struct inode *inode, struct file *filp, + unsigned int command, unsigned long arg) { struct raw_config_request rq; struct raw_device_data *rawdev; - int err; - + int err = 0; + switch (command) { case RAW_SETBIND: case RAW_GETBIND: /* First, find out which raw minor we want */ - err = -EFAULT; - if (copy_from_user(&rq, (void *) arg, sizeof(rq))) + if (copy_from_user(&rq, (void *) arg, sizeof(rq))) { + err = -EFAULT; goto out; - - err = -EINVAL; - if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS) + } + + if (rq.raw_minor < 0 || rq.raw_minor >= MAX_RAW_MINORS) { + err = -EINVAL; goto out; + } rawdev = &raw_devices[rq.raw_minor]; if (command == RAW_SETBIND) { @@ -152,9 +153,10 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp, * This is like making block devices, so demand the * same capability */ - err = -EPERM; - if (!capable(CAP_SYS_ADMIN)) + if (!capable(CAP_SYS_ADMIN)) { + err = -EPERM; goto out; + } /* * For now, we don't need to check that the underlying @@ -163,17 +165,18 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp, * major/minor numbers make sense. */ - err = -EINVAL; dev = MKDEV(rq.block_major, rq.block_minor); if ((rq.block_major == 0 && rq.block_minor != 0) || - MAJOR(dev) != rq.block_major || - MINOR(dev) != rq.block_minor) + MAJOR(dev) != rq.block_major || + MINOR(dev) != rq.block_minor) { + err = -EINVAL; goto out; - + } + down(&raw_mutex); - err = -EBUSY; if (rawdev->inuse) { up(&raw_mutex); + err = -EBUSY; goto out; } if (rawdev->binding) { @@ -185,7 +188,10 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp, rawdev->binding = NULL; } else { rawdev->binding = bdget(dev); - MOD_INC_USE_COUNT; + if (rawdev->binding == NULL) + err = -ENOMEM; + else + try_module_get(THIS_MODULE); } up(&raw_mutex); } else { @@ -200,13 +206,12 @@ raw_ctl_ioctl(struct inode *inode, struct file *filp, rq.block_major = rq.block_minor = 0; } up(&raw_mutex); - err = -EFAULT; - if (copy_to_user((void *)arg, &rq, sizeof(rq))) + if (copy_to_user((void *)arg, &rq, sizeof(rq))) { + err = -EFAULT; goto out; + } } - err = 0; break; - default: err = -EINVAL; break; -- cgit v1.2.3 From 76c25284e0d845bff4ee1031721556148af4db1c Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 20 Mar 2003 05:48:33 -0800 Subject: [PATCH] Fix floppy oops on forced unload From: Angus Sawyer Prevent OOPS on removing floppy driver with "rmmod -f floppy". floppy.c would attempt to unregister resources for nonexistent device. Patch stops the driver attempting to register and unregister the nonexistent device by removing the drive from the allowed drives mask (defaults to present). --- drivers/block/floppy.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index d3d20c946e30..c8b909229c5d 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3649,6 +3649,8 @@ static void __init config_types(void) name = default_drive_params[type].name; allowed_drive_mask |= 1 << drive; } + else + allowed_drive_mask &= ~(1 << drive); } else { params = &default_drive_params[0].params; sprintf(temparea, "unknown type %d (usb?)", type); -- cgit v1.2.3 From ea3323f13be854779ead45c28d2db5cbb46e6ec7 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Mar 2003 05:53:52 -0800 Subject: [PATCH] fix obvious thinko --- drivers/cdrom/cdu31a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cdrom/cdu31a.c b/drivers/cdrom/cdu31a.c index f25d9ff0fda2..915afe6dfe71 100644 --- a/drivers/cdrom/cdu31a.c +++ b/drivers/cdrom/cdu31a.c @@ -1375,9 +1375,9 @@ read_data_block(char *buffer, readahead_buffer + (2048 - readahead_dataleft), readahead_dataleft); - readahead_dataleft = 0; bytesleft -= readahead_dataleft; offset += readahead_dataleft; + readahead_dataleft = 0; } else { /* The readahead will fill the whole buffer, get the data and return. */ -- cgit v1.2.3 From cd39bcebd7cd56e54f070a344f54892cced255f8 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Mar 2003 05:54:00 -0800 Subject: [PATCH] cciss unregister cleanup From Herbert Xu The following patches against 2.4 and 2.5 makes cciss unregister properly if initialisation fails. --- drivers/block/cciss.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 734ae3817430..642920295653 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -2623,12 +2623,8 @@ int __init cciss_init(void) { printk(KERN_INFO DRIVER_NAME "\n"); - /* Register for out PCI devices */ - if (pci_register_driver(&cciss_pci_driver) > 0 ) - return 0; - else - return -ENODEV; - + /* Register for our PCI devices */ + return pci_register_driver(&cciss_pci_driver); } static int __init init_cciss_module(void) -- cgit v1.2.3 From 582b70ecdbdc3c093a643d2c0b653cb9f3520fbd Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Mar 2003 05:54:11 -0800 Subject: [PATCH] 3ware vendor update --- drivers/scsi/3w-xxxx.c | 435 +++++++++++++++++++++++++++++++++++++++++-------- drivers/scsi/3w-xxxx.h | 33 +++- 2 files changed, 393 insertions(+), 75 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index 2652645219fb..c90651671cae 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -6,7 +6,7 @@ Arnaldo Carvalho de Melo Brad Strand - Copyright (C) 1999-2002 3ware Inc. + Copyright (C) 1999-2003 3ware Inc. Kernel compatiblity By: Andre Hedrick Non-Copyright (C) 2000 Andre Hedrick @@ -164,6 +164,11 @@ Add support for mode sense opcode. Add support for cache mode page. Add support for synchronize cache opcode. + 1.02.00.032 - Fix small multicard rollcall bug. + Make driver stay loaded with no units for hot add/swap. + Add support for "twe" character device for ioctls. + Clean up request_id queueing code. + Fix tw_scsi_queue() spinlocks. */ #include @@ -203,6 +208,9 @@ MODULE_LICENSE("GPL"); #include "3w-xxxx.h" +static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg); +static int tw_chrdev_open(struct inode *inode, struct file *file); +static int tw_chrdev_release(struct inode *inode, struct file *file); static int tw_copy_info(TW_Info *info, char *fmt, ...); static void tw_copy_mem_info(TW_Info *info, char *data, int len); static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs); @@ -216,10 +224,19 @@ static struct notifier_block tw_notifier = { tw_halt, NULL, 0 }; +/* File operations struct for character device */ +static struct file_operations tw_fops = { + owner: THIS_MODULE, + ioctl: tw_chrdev_ioctl, + open: tw_chrdev_open, + release: tw_chrdev_release +}; + /* Globals */ -char *tw_driver_version="1.02.00.031"; +char *tw_driver_version="1.02.00.032"; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; int tw_device_extension_count = 0; +static int twe_major = -1; /* Functions */ @@ -599,6 +616,209 @@ int tw_check_errors(TW_Device_Extension *tw_dev) return 0; } /* End tw_check_errors() */ +/* This function handles ioctl for the character device */ +static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int error, request_id; + dma_addr_t dma_handle; + unsigned short tw_aen_code; + struct timeval before, timeout; + unsigned long flags = 0x0; + unsigned int data_buffer_length = 0; + unsigned long data_buffer_length_adjusted = 0; + unsigned long *cpu_addr; + TW_New_Ioctl *tw_ioctl; + TW_Passthru *passthru; + TW_Device_Extension *tw_dev = tw_device_extension_list[minor(inode->i_rdev)]; + + dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n"); + + /* Only let one of these through at a time */ + if (test_and_set_bit(TW_IN_CHRDEV_IOCTL, &tw_dev->flags)) { + return -EBUSY; + } + + /* First copy down the buffer length */ + error = copy_from_user(&data_buffer_length, (void *)arg, sizeof(unsigned int)); + if (error) { + printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Error copying buffer length from userspace.\n"); + clear_bit(TW_IN_CHRDEV_IOCTL, &tw_dev->flags); + return -EFAULT; + } + + /* Check size */ + if (data_buffer_length > TW_MAX_SECTORS * 512) { + printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Invalid buffer size (%d).\n", data_buffer_length); + clear_bit(TW_IN_CHRDEV_IOCTL, &tw_dev->flags); + return -EFAULT; + } + + /* Hardware can only do multiple of 512 byte transfers */ + if (data_buffer_length % 512) + data_buffer_length_adjusted = data_buffer_length + 512 - (data_buffer_length % 512); + else + data_buffer_length_adjusted = data_buffer_length; + + /* Now allocate ioctl buf memory */ + cpu_addr = pci_alloc_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, &dma_handle); + if (cpu_addr == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Error allocating memory.\n"); + clear_bit(TW_IN_CHRDEV_IOCTL, &tw_dev->flags); + return -ENOMEM; + } + + tw_ioctl = (TW_New_Ioctl *)cpu_addr; + + /* Now copy down the entire ioctl */ + error = copy_from_user(tw_ioctl, (void *)arg, data_buffer_length + sizeof(TW_New_Ioctl) - 1); + if (error) { + printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Error copying data from userspace.\n"); + pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); + clear_bit(TW_IN_CHRDEV_IOCTL, &tw_dev->flags); + return -EFAULT; + } + + passthru = (TW_Passthru *)&tw_ioctl->firmware_command; + + /* See which ioctl we are doing */ + switch (cmd) { + case TW_OP_NOP: + dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_OP_NOP.\n"); + break; + case TW_OP_AEN_LISTEN: + dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_AEN_LISTEN.\n"); + memset(tw_ioctl->data_buffer, 0, tw_ioctl->data_buffer_length); + if (tw_dev->aen_head == tw_dev->aen_tail) { + tw_aen_code = TW_AEN_QUEUE_EMPTY; + } else { + tw_aen_code = tw_dev->aen_queue[tw_dev->aen_head]; + if (tw_dev->aen_head == TW_Q_LENGTH - 1) { + tw_dev->aen_head = TW_Q_START; + } else { + tw_dev->aen_head = tw_dev->aen_head + 1; + } + } + memcpy(tw_ioctl->data_buffer, &tw_aen_code, sizeof(tw_aen_code)); + break; + case TW_CMD_PACKET_WITH_DATA: + dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): caught TW_CMD_PACKET_WITH_DATA.\n"); + spin_lock_irqsave(&tw_dev->tw_lock, flags); + + tw_state_request_start(tw_dev, &request_id); + + /* Flag internal command */ + tw_dev->srb[request_id] = 0; + + /* Flag chrdev ioctl */ + tw_dev->chrdev_request_id = request_id; + + tw_ioctl->firmware_command.request_id = request_id; + + /* Load the sg list */ + switch (tw_ioctl->firmware_command.byte0.sgl_offset) { + case 2: + tw_ioctl->firmware_command.byte8.param.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1; + tw_ioctl->firmware_command.byte8.param.sgl[0].length = data_buffer_length_adjusted; + break; + case 3: + tw_ioctl->firmware_command.byte8.io.sgl[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1; + tw_ioctl->firmware_command.byte8.io.sgl[0].length = data_buffer_length_adjusted; + break; + case 5: + passthru->sg_list[0].address = dma_handle + sizeof(TW_New_Ioctl) - 1; + passthru->sg_list[0].length = data_buffer_length_adjusted; + break; + } + + memcpy(tw_dev->command_packet_virtual_address[request_id], &(tw_ioctl->firmware_command), sizeof(TW_Command)); + + /* Now post the command packet to the controller */ + tw_post_command_packet(tw_dev, request_id); + spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + + /* Now wait for the command to complete */ + do_gettimeofday(&before); + + tw_ioctl_chrdev_retry: + + if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { + interruptible_sleep_on_timeout(&tw_dev->ioctl_wqueue, 1); + do_gettimeofday(&timeout); + if (before.tv_sec + TW_IOCTL_CHRDEV_TIMEOUT < timeout.tv_sec) { + /* Now we need to reset the board */ + printk(KERN_WARNING "3w-xxxx: scsi%d: Character ioctl (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, cmd); + spin_lock_irqsave(&tw_dev->tw_lock, flags); + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); + tw_dev->posted_request_count--; + if (tw_reset_device_extension(tw_dev)) { + printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Reset failed for card %d.\n", tw_dev->host->host_no); + } + spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + clear_bit(TW_IN_CHRDEV_IOCTL, &tw_dev->flags); + if (signal_pending(current)) + return -EINTR; + else + return -EIO; + } else { + goto tw_ioctl_chrdev_retry; + } + } + + /* Now copy in the command packet response */ + memcpy(&(tw_ioctl->firmware_command), tw_dev->command_packet_virtual_address[request_id], sizeof(TW_Command)); + + /* Now complete the io */ + spin_lock_irqsave(&tw_dev->tw_lock, flags); + tw_dev->posted_request_count--; + tw_dev->state[request_id] = TW_S_COMPLETED; + tw_state_request_finish(tw_dev, request_id); + spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + break; + default: + printk(KERN_WARNING "3w-xxxx: Unknown chrdev ioctl 0x%x.\n", cmd); + } + + /* Now copy the response to userspace */ + error = copy_to_user((void *)arg, tw_ioctl, sizeof(TW_New_Ioctl) + tw_ioctl->data_buffer_length - 1); + if (error) { + printk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl(): Error copying data to userspace.\n"); + pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); + clear_bit(TW_IN_CHRDEV_IOCTL, &tw_dev->flags); + return -EFAULT; + } + + /* Now free ioctl buf memory */ + pci_free_consistent(tw_dev->tw_pci_dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle); + + clear_bit(TW_IN_CHRDEV_IOCTL, &tw_dev->flags); + + return 0; +} /* End tw_chrdev_ioctl() */ + +/* This function handles open for the character device */ +static int tw_chrdev_open(struct inode *inode, struct file *file) +{ + unsigned int minor_number; + + dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n"); + + minor_number = minor(inode->i_rdev); + if (minor_number >= tw_device_extension_count) + return -ENODEV; + + return 0; +} /* End tw_chrdev_open() */ + +/* This function handles close for the character device */ +static int tw_chrdev_release(struct inode *inode, struct file *file) +{ + dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_release()\n"); + + return 0; +} /* End tw_chrdev_release() */ + /* This function will clear all interrupts on the controller */ void tw_clear_all_interrupts(TW_Device_Extension *tw_dev) { @@ -867,7 +1087,9 @@ int tw_findcards(Scsi_Host_Template *tw_host) /* Disable interrupts on the card */ tw_disable_interrupts(tw_dev); - + + tries = 0; + while (tries < TW_MAX_RESET_TRIES) { /* Do soft reset */ tw_soft_reset(tw_dev); @@ -897,8 +1119,8 @@ int tw_findcards(Scsi_Host_Template *tw_host) continue; } - /* Make sure that io region isn't already taken */ - if (check_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE)) { + /* Reserve the io address space */ + if (!request_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME)) { printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't get io range 0x%lx-0x%lx for card %d.\n", (tw_dev->tw_pci_dev->resource[0].start), (tw_dev->tw_pci_dev->resource[0].start) + @@ -907,16 +1129,10 @@ int tw_findcards(Scsi_Host_Template *tw_host) kfree(tw_dev); continue; } - - /* Reserve the io address space */ - request_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME); + error = tw_initialize_units(tw_dev); if (error) { printk(KERN_WARNING "3w-xxxx: No valid units for for card %d.\n", j); - release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); - tw_free_device_extension(tw_dev); - kfree(tw_dev); - continue; } error = tw_initconnection(tw_dev, TW_INIT_MESSAGE_CREDITS); @@ -935,7 +1151,7 @@ int tw_findcards(Scsi_Host_Template *tw_host) if (tw_dev->num_units > 0) { /* Use SHT cmd_per_lun here */ tw_dev->free_head = TW_Q_START; - tw_dev->free_tail = TW_Q_LENGTH - 1; + tw_dev->free_tail = TW_Q_START; tw_dev->free_wrap = TW_Q_LENGTH - 1; } @@ -992,13 +1208,7 @@ int tw_findcards(Scsi_Host_Template *tw_host) /* Tell the firmware we support shutdown notification*/ error = tw_setfeature(tw_dev2, 2, 1, &c); if (error) { - printk(KERN_WARNING "3w-xxxx: tw_setfeature(): Error setting features for card %d.\n", j); - scsi_unregister(host); - release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); - tw_free_device_extension(tw_dev); - kfree(tw_dev); - numcards--; - continue; + printk(KERN_WARNING "3w-xxxx: Unable to set features for card %d, old firmware or card.\n", j); } /* Now setup the interrupt handler */ @@ -1023,10 +1233,14 @@ int tw_findcards(Scsi_Host_Template *tw_host) } } - if (numcards == 0) - printk(KERN_WARNING "3w-xxxx: No cards with valid units found.\n"); - else - register_reboot_notifier(&tw_notifier); + if (numcards == 0) { + printk(KERN_WARNING "3w-xxxx: No cards found.\n"); + } else { + register_reboot_notifier(&tw_notifier); + if ((twe_major = register_chrdev (0, "twe", &tw_fops)) < 0) { + printk(KERN_WARNING "3w-xxxx: Unable to register \"twe\" character device, error = %d.\n", twe_major); + } + } return numcards; } /* End tw_findcards() */ @@ -1153,6 +1367,8 @@ int tw_initialize_device_extension(TW_Device_Extension *tw_dev) tw_dev->pending_head = TW_Q_START; tw_dev->pending_tail = TW_Q_START; spin_lock_init(&tw_dev->tw_lock); + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; + init_waitqueue_head(&tw_dev->ioctl_wqueue); return 0; } /* End tw_initialize_device_extension() */ @@ -1395,9 +1611,14 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) /* Check for internal command completion */ if (tw_dev->srb[request_id] == 0) { dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n"); - retval = tw_aen_complete(tw_dev, request_id); - if (retval) { - printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no); + /* Check for chrdev ioctl completion */ + if (request_id != tw_dev->chrdev_request_id) { + retval = tw_aen_complete(tw_dev, request_id); + if (retval) { + printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no); + } + } else { + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; } } else { switch (tw_dev->srb[request_id]->cmnd[0]) { @@ -1409,6 +1630,10 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) case WRITE_6: dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught WRITE_10/WRITE_6\n"); break; + case TEST_UNIT_READY: + dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught TEST_UNIT_READY\n"); + error = tw_scsiop_test_unit_ready_complete(tw_dev, request_id); + break; case INQUIRY: dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): caught INQUIRY\n"); error = tw_scsiop_inquiry_complete(tw_dev, request_id); @@ -2070,12 +2295,13 @@ int tw_reset_device_extension(TW_Device_Extension *tw_dev) tw_dev->state[i] = TW_S_INITIAL; } tw_dev->free_head = TW_Q_START; - tw_dev->free_tail = TW_Q_LENGTH - 1; + tw_dev->free_tail = TW_Q_START; tw_dev->posted_request_count = 0; tw_dev->pending_request_count = 0; tw_dev->pending_head = TW_Q_START; tw_dev->pending_tail = TW_Q_START; tw_dev->reset_print = 0; + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; return 0; } /* End tw_reset_device_extension() */ @@ -2357,7 +2583,6 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) unsigned char *command = SCpnt->cmnd; int request_id = 0; int error = 0; - unsigned long flags = 0; TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata; if (tw_dev == NULL) { @@ -2367,14 +2592,14 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) return 0; } - spin_lock_irqsave(&tw_dev->tw_lock, flags); + spin_lock(&tw_dev->tw_lock); dprintk(KERN_NOTICE "3w-xxxx: tw_scsi_queue()\n"); /* Skip scsi command if it isn't for us */ - if ((tw_dev->is_unit_present[SCpnt->device->id] == FALSE) || (SCpnt->device->lun != 0)) { + if ((SCpnt->device->channel != 0) || (SCpnt->device->lun != 0)) { SCpnt->result = (DID_BAD_TARGET << 16); done(SCpnt); - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + spin_unlock(&tw_dev->tw_lock); return 0; } @@ -2387,6 +2612,9 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) /* Save the scsi command for use by the ISR */ tw_dev->srb[request_id] = SCpnt; + /* Initialize phase to zero */ + SCpnt->SCp.phase = 0; + switch (*command) { case READ_10: case READ_6: @@ -2436,7 +2664,7 @@ int tw_scsi_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) SCpnt->result = (DID_ERROR << 16); done(SCpnt); } - spin_unlock_irqrestore(&tw_dev->tw_lock, flags); + spin_unlock(&tw_dev->tw_lock); return 0; } /* End tw_scsi_queue() */ @@ -2460,6 +2688,12 @@ int tw_scsi_release(struct Scsi_Host *tw_host) /* Free up the IRQ */ free_irq(tw_dev->tw_pci_dev->irq, tw_dev); + /* Unregister character device */ + if (twe_major >= 0) { + unregister_chrdev(twe_major, "twe"); + twe_major = -1; + } + /* Free up device extension resources */ tw_free_device_extension(tw_dev); @@ -2533,7 +2767,6 @@ int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) { unsigned char *is_unit_present; unsigned char *request_buffer; - int i; TW_Param *param; dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete()\n"); @@ -2545,12 +2778,12 @@ int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) } request_buffer = tw_dev->srb[request_id]->request_buffer; memset(request_buffer, 0, tw_dev->srb[request_id]->request_bufflen); - request_buffer[0] = TYPE_DISK; /* Peripheral device type */ - request_buffer[1] = 0; /* Device type modifier */ - request_buffer[2] = 0; /* No ansi/iso compliance */ - request_buffer[4] = 31; /* Additional length */ + request_buffer[0] = TYPE_DISK; /* Peripheral device type */ + request_buffer[1] = 0; /* Device type modifier */ + request_buffer[2] = 0; /* No ansi/iso compliance */ + request_buffer[4] = 31; /* Additional length */ memcpy(&request_buffer[8], "3ware ", 8); /* Vendor ID */ - memcpy(&request_buffer[16], "3w-xxxx ", 16); /* Product ID */ + sprintf(&request_buffer[16], "Logical Disk %-2d ", tw_dev->srb[request_id]->device->id); memcpy(&request_buffer[32], tw_driver_version, 3); param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; @@ -2560,15 +2793,12 @@ int tw_scsiop_inquiry_complete(TW_Device_Extension *tw_dev, int request_id) } is_unit_present = &(param->data[0]); - for (i=0 ; iis_unit_present[i] = FALSE; - } else { - if (is_unit_present[i] & TW_UNIT_ONLINE) { - tw_dev->is_unit_present[i] = TRUE; - dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_inquiry_complete: Unit %d found.\n", i); - } - } + if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) { + tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = TRUE; + } else { + tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = FALSE; + tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16); + return TW_ISR_DONT_RESULT; } return 0; @@ -2946,17 +3176,88 @@ int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id) /* This function will handle test unit ready scsi command */ int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id) { + TW_Param *param; + TW_Command *command_packet; + unsigned long command_que_value; + u32 command_que_addr; + unsigned long param_value; + dprintk(KERN_NOTICE "3w-xxxx: tw_scsiop_test_unit_ready()\n"); - /* Tell the scsi layer were done */ - tw_dev->state[request_id] = TW_S_COMPLETED; - tw_state_request_finish(tw_dev, request_id); - tw_dev->srb[request_id]->result = (DID_OK << 16); - tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]); + /* Initialize command packet */ + command_que_addr = tw_dev->registers.command_que_addr; + command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; + if (command_packet == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet virtual address.\n"); + return 1; + } + memset(command_packet, 0, sizeof(TW_Sector)); + command_packet->byte0.opcode = TW_OP_GET_PARAM; + command_packet->byte0.sgl_offset = 2; + command_packet->size = 4; + command_packet->request_id = request_id; + command_packet->byte3.unit = 0; + command_packet->byte3.host_id = 0; + command_packet->status = 0; + command_packet->flags = 0; + command_packet->byte6.parameter_count = 1; + + /* Now setup the param */ + if (tw_dev->alignment_virtual_address[request_id] == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment virtual address.\n"); + return 1; + } + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + memset(param, 0, sizeof(TW_Sector)); + param->table_id = 3; /* unit summary table */ + param->parameter_id = 3; /* unitsstatus parameter */ + param->parameter_size_bytes = TW_MAX_UNITS; + param_value = tw_dev->alignment_physical_address[request_id]; + if (param_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad alignment physical address.\n"); + return 1; + } + + command_packet->byte8.param.sgl[0].address = param_value; + command_packet->byte8.param.sgl[0].length = sizeof(TW_Sector); + command_que_value = tw_dev->command_packet_physical_address[request_id]; + if (command_que_value == 0) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready(): Bad command packet physical address.\n"); + return 1; + } + + /* Now try to post the command packet */ + tw_post_command_packet(tw_dev, request_id); return 0; } /* End tw_scsiop_test_unit_ready() */ +/* This function is called by the isr to complete a testunitready command */ +int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id) +{ + unsigned char *is_unit_present; + TW_Param *param; + + dprintk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete()\n"); + + param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; + if (param == NULL) { + printk(KERN_WARNING "3w-xxxx: tw_scsiop_test_unit_ready_complete(): Bad alignment virtual address.\n"); + return 1; + } + is_unit_present = &(param->data[0]); + + if (is_unit_present[tw_dev->srb[request_id]->device->id] & TW_UNIT_ONLINE) { + tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = TRUE; + } else { + tw_dev->is_unit_present[tw_dev->srb[request_id]->device->id] = FALSE; + tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16); + return TW_ISR_DONT_RESULT; + } + + return 0; +} /* End tw_scsiop_test_unit_ready_complete() */ + /* Set a value in the features table */ int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, unsigned char *val) @@ -3091,17 +3392,13 @@ int tw_state_request_finish(TW_Device_Extension *tw_dev, int request_id) { dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish()\n"); - do { - if (tw_dev->free_tail == tw_dev->free_wrap) { - tw_dev->free_tail = TW_Q_START; - } else { - tw_dev->free_tail = tw_dev->free_tail + 1; - } - } while ((tw_dev->state[tw_dev->free_queue[tw_dev->free_tail]] != TW_S_COMPLETED)); - tw_dev->free_queue[tw_dev->free_tail] = request_id; - tw_dev->state[request_id] = TW_S_FINISHED; + if (tw_dev->free_tail == tw_dev->free_wrap) + tw_dev->free_tail = TW_Q_START; + else + tw_dev->free_tail++; + dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_finish(): Freeing request_id %d\n", request_id); return 0; @@ -3115,20 +3412,16 @@ int tw_state_request_start(TW_Device_Extension *tw_dev, int *request_id) dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start()\n"); /* Obtain next free request_id */ - do { - if (tw_dev->free_head == tw_dev->free_wrap) { - tw_dev->free_head = TW_Q_START; - } else { - tw_dev->free_head = tw_dev->free_head + 1; - } - } while (tw_dev->state[tw_dev->free_queue[tw_dev->free_head]] & TW_START_MASK); - id = tw_dev->free_queue[tw_dev->free_head]; + if (tw_dev->free_head == tw_dev->free_wrap) + tw_dev->free_head = TW_Q_START; + else + tw_dev->free_head++; - dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id); *request_id = id; tw_dev->state[id] = TW_S_STARTED; + dprintk(KERN_NOTICE "3w-xxxx: tw_state_request_start(): id = %d.\n", id); return 0; } /* End tw_state_request_start() */ diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 48a550c4107f..7c1947966d66 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h @@ -6,7 +6,7 @@ Arnaldo Carvalho de Melo Brad Strand - Copyright (C) 1999-2002 3ware Inc. + Copyright (C) 1999-2003 3ware Inc. Kernel compatiblity By: Andre Hedrick Non-Copyright (C) 2000 Andre Hedrick @@ -113,11 +113,11 @@ static unsigned char tw_sense_table[][4] = {0x84, 0x0b, 0x47, 0x00}, // Data CRC error SCSI parity error {0xd0, 0x0b, 0x00, 0x00}, // Device busy Aborted command {0xd1, 0x0b, 0x00, 0x00}, // Device busy Aborted command + {0x37, 0x02, 0x04, 0x00}, // Unit offline Not ready /* Codes for older firmware */ // 3ware Error SCSI Error {0x09, 0x0b, 0x00, 0x00}, // Unrecovered disk error Aborted command - {0x37, 0x0b, 0x04, 0x00}, // Unit offline Logical unit not ready {0x51, 0x0b, 0x00, 0x00} // Unspecified Aborted command }; @@ -219,18 +219,23 @@ static unsigned char tw_sense_table[][4] = #define TW_MAX_PCI_BUSES 255 #define TW_MAX_RESET_TRIES 3 #define TW_UNIT_INFORMATION_TABLE_BASE 0x300 -#define TW_MAX_CMDS_PER_LUN 255 +#define TW_MAX_CMDS_PER_LUN 254 /* 254 for io, 1 for + chrdev ioctl, one for + internal aen post */ #define TW_BLOCK_SIZE 0x200 /* 512-byte blocks */ #define TW_IOCTL 0x80 #define TW_UNIT_ONLINE 1 #define TW_IN_INTR 1 #define TW_IN_IOCTL 2 +#define TW_IN_CHRDEV_IOCTL 3 #define TW_MAX_SECTORS 256 #define TW_AEN_WAIT_TIME 1000 #define TW_IOCTL_WAIT_TIME (1 * HZ) /* 1 second */ #define TW_ISR_DONT_COMPLETE 2 #define TW_ISR_DONT_RESULT 3 #define TW_IOCTL_TIMEOUT 25 /* 25 seconds */ +#define TW_IOCTL_CHRDEV_TIMEOUT 25 /* 25 seconds */ +#define TW_IOCTL_CHRDEV_FREE -1 /* Macros */ #define TW_STATUS_ERRORS(x) \ @@ -246,6 +251,8 @@ static unsigned char tw_sense_table[][4] = #define dprintk(msg...) do { } while(0) #endif +#pragma pack(1) + /* Scatter Gather List Entry */ typedef struct TAG_TW_SG_Entry { u32 address; @@ -295,6 +302,8 @@ typedef struct TW_Command { } byte8; } TW_Command; +#pragma pack() + typedef struct TAG_TW_Ioctl { unsigned char opcode; unsigned short table_id; @@ -304,6 +313,16 @@ typedef struct TAG_TW_Ioctl { unsigned char data[1]; } TW_Ioctl; +#pragma pack(1) + +/* Structure for new chardev ioctls */ +typedef struct TAG_TW_New_Ioctl { + unsigned int data_buffer_length; + unsigned char padding [508]; + TW_Command firmware_command; + char data_buffer[1]; +} TW_New_Ioctl; + /* GetParam descriptor */ typedef struct { unsigned short table_id; @@ -414,8 +433,12 @@ typedef struct TAG_TW_Device_Extension { unsigned long *ioctl_data[TW_Q_LENGTH]; int reset_print; char online; + volatile int chrdev_request_id; + wait_queue_head_t ioctl_wqueue; } TW_Device_Extension; +#pragma pack() + /* Function prototypes */ int tw_aen_complete(TW_Device_Extension *tw_dev, int request_id); int tw_aen_drain_queue(TW_Device_Extension *tw_dev); @@ -463,6 +486,7 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id); int tw_scsiop_request_sense(TW_Device_Extension *tw_dev, int request_id); int tw_scsiop_synchronize_cache(TW_Device_Extension *tw_dev, int request_id); int tw_scsiop_test_unit_ready(TW_Device_Extension *tw_dev, int request_id); +int tw_scsiop_test_unit_ready_complete(TW_Device_Extension *tw_dev, int request_id); int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, unsigned char *val); int tw_setup_irq(TW_Device_Extension *tw_dev); @@ -483,9 +507,10 @@ void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev); .eh_abort_handler = tw_scsi_eh_abort, \ .eh_host_reset_handler = tw_scsi_eh_reset, \ .bios_param = tw_scsi_biosparam, \ - .can_queue = TW_Q_LENGTH-1, \ + .can_queue = TW_Q_LENGTH-2, \ .this_id = -1, \ .sg_tablesize = TW_MAX_SGL_LENGTH, \ + .max_sectors = TW_MAX_SECTORS, \ .cmd_per_lun = TW_MAX_CMDS_PER_LUN, \ .present = 0, \ .unchecked_isa_dma = 0, \ -- cgit v1.2.3 From bf590c40e10f95930ab5543c304bd3b8cd3b81c6 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Mar 2003 05:54:22 -0800 Subject: [PATCH] Remove old DRM4.0 code. Old patch from John Kim to remove old DRM 4.0 code in 2.5.59. --- drivers/char/drm/i830_dma.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index dbffc3ced84a..0f65f959c0dd 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c @@ -40,12 +40,6 @@ #include /* For task queue support */ #include -#ifdef DO_MUNMAP_4_ARGS -#define DO_MUNMAP(m, a, l) do_munmap(m, a, l, 1) -#else -#define DO_MUNMAP(m, a, l) do_munmap(m, a, l) -#endif - #define I830_BUF_FREE 2 #define I830_BUF_CLIENT 1 #define I830_BUF_HARDWARE 0 @@ -230,7 +224,7 @@ static int i830_unmap_buffer(drm_buf_t *buf) return -EINVAL; down_write(¤t->mm->mmap_sem); - retcode = DO_MUNMAP(current->mm, + retcode = do_munmap(current->mm, (unsigned long)buf_priv->virtual, (size_t) buf->total); up_write(¤t->mm->mmap_sem); -- cgit v1.2.3 From 470aab84028501f3bac7a9e471409e98c014002e Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Mar 2003 05:54:39 -0800 Subject: [PATCH] piix compile fix for CONFIG_PROC_FS=n Fix by Randy Dunlap Here's a patch to build ide/pci/piix.c with CONFIG_PROC_FS=n. --- drivers/ide/pci/piix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c index a67b113cbce2..2fe946fce0aa 100644 --- a/drivers/ide/pci/piix.c +++ b/drivers/ide/pci/piix.c @@ -106,6 +106,7 @@ #include "ide_modes.h" #include "piix.h" +static int no_piix_dma; #if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) #include #include @@ -114,7 +115,6 @@ static u8 piix_proc = 0; #define PIIX_MAX_DEVS 5 static struct pci_dev *piix_devs[PIIX_MAX_DEVS]; static int n_piix_devs; -static int no_piix_dma = 0; /** * piix_get_info - fill in /proc for PIIX ide -- cgit v1.2.3 From a978d7792cefb17d1b222af2aeb0efe5ac506bcd Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Mar 2003 05:55:14 -0800 Subject: [PATCH] fix acpi write throttle seq file breakage. From Pavel Machek --- drivers/acpi/processor.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/processor.c b/drivers/acpi/processor.c index 3940e529afae..fb8cd6bcc4cb 100644 --- a/drivers/acpi/processor.c +++ b/drivers/acpi/processor.c @@ -1356,7 +1356,8 @@ acpi_processor_write_throttling ( loff_t *data) { int result = 0; - struct acpi_processor *pr = (struct acpi_processor *) data; + struct seq_file *m = (struct seq_file *)file->private_data; + struct acpi_processor *pr = (struct acpi_processor *)m->private; char state_string[12] = {'\0'}; ACPI_FUNCTION_TRACE("acpi_processor_write_throttling"); @@ -1418,7 +1419,8 @@ acpi_processor_write_limit ( loff_t *data) { int result = 0; - struct acpi_processor *pr = (struct acpi_processor *) data; + struct seq_file *m = (struct seq_file *)file->private_data; + struct acpi_processor *pr = (struct acpi_processor *)m->private; char limit_string[25] = {'\0'}; int px = 0; int tx = 0; -- cgit v1.2.3 From 46f2cb79f396f634bfb1af35e642cf5e7eb418a4 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Mar 2003 05:55:47 -0800 Subject: [PATCH] make nbd working in 2.5.x From Petr Vandrovec we use nbd for our diskless systems, and it looks to me like that it has some serious problems in 2.5.x... Can you apply this patch and forward it to Linus? There were: * Missing disk's queue initialization * Driver should use list_del_init: put_request now verifies that req->queuelist is empty, and list_del was incompatible with this. * I converted nbd_end_request back to end_that_request_{first,last} as I saw no reason why driver should do it itself... and blk_put_request has no place under queue_lock, so apparently when semantic changed nobody went through drivers... --- drivers/block/nbd.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 001b2f98267e..08298857a712 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -76,22 +76,15 @@ static void nbd_end_request(struct request *req) { int uptodate = (req->errors == 0) ? 1 : 0; request_queue_t *q = req->q; - struct bio *bio; - unsigned nsect; unsigned long flags; #ifdef PARANOIA requests_out++; #endif spin_lock_irqsave(q->queue_lock, flags); - while((bio = req->bio) != NULL) { - nsect = bio_sectors(bio); - blk_finished_io(nsect); - req->bio = bio->bi_next; - bio->bi_next = NULL; - bio_endio(bio, nsect << 9, uptodate ? 0 : -EIO); + if (!end_that_request_first(req, uptodate, req->nr_sectors)) { + end_that_request_last(req); } - blk_put_request(req); spin_unlock_irqrestore(q->queue_lock, flags); } @@ -243,7 +236,7 @@ static struct request *nbd_find_request(struct nbd_device *lo, char *handle) req = list_entry(tmp, struct request, queuelist); if (req != xreq) continue; - list_del(&req->queuelist); + list_del_init(&req->queuelist); spin_unlock(&lo->queue_lock); return req; } @@ -322,7 +315,7 @@ void nbd_clear_que(struct nbd_device *lo) spin_lock(&lo->queue_lock); if (!list_empty(&lo->queue_head)) { req = list_entry(lo->queue_head.next, struct request, queuelist); - list_del(&req->queuelist); + list_del_init(&req->queuelist); } spin_unlock(&lo->queue_lock); if (req) { @@ -387,7 +380,7 @@ static void do_nbd_request(request_queue_t * q) if (req->errors) { printk(KERN_ERR "nbd: nbd_send_req failed\n"); spin_lock(&lo->queue_lock); - list_del(&req->queuelist); + list_del_init(&req->queuelist); spin_unlock(&lo->queue_lock); nbd_end_request(req); spin_lock_irq(q->queue_lock); @@ -590,6 +583,7 @@ static int __init nbd_init(void) disk->first_minor = i; disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; + disk->queue = &nbd_queue; sprintf(disk->disk_name, "nbd%d", i); set_capacity(disk, 0x3ffffe); add_disk(disk); -- cgit v1.2.3 From a50f92a6bc3b75e01012e27a56a7a7a76bba7c85 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Thu, 20 Mar 2003 05:58:12 -0800 Subject: [PATCH] Several logic bugs. Lots of patches from Norbert Kiesel that fix up several silly | vs. || and & vs. && bugs found with find ${1:-.} -name \*.c | xargs grep -En \ '![a-zA-Z0-9_ ]+(\|[^|]|\&[^&])|([^|]\||[^&]\&) *!' --- drivers/media/dvb/dvb-core/dvb_demux.c | 2 +- drivers/pnp/pnpbios/core.c | 4 ++-- drivers/serial/uart00.c | 4 ++-- drivers/video/console/fbcon.c | 2 +- sound/oss/gus_midi.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c index 29289ef75d1b..d9e2735afddf 100644 --- a/drivers/media/dvb/dvb-core/dvb_demux.c +++ b/drivers/media/dvb/dvb-core/dvb_demux.c @@ -221,7 +221,7 @@ dvb_dmx_swfilter_sectionfilter(struct dvb_demux_feed *dvbdmxfeed, return 0; neq|=f->maskandnotmode[i]&xor; } - if (f->doneq & !neq) + if (f->doneq && !neq) return 0; return dvbdmxfeed->cb.sec(dvbdmxfeed->secbuf, dvbdmxfeed->seclen, diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c index 69176c1ef875..2e33b62d2d3f 100644 --- a/drivers/pnp/pnpbios/core.c +++ b/drivers/pnp/pnpbios/core.c @@ -322,7 +322,7 @@ static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node u16 status; if (!pnp_bios_present()) return PNP_FUNCTION_NOT_SUPPORTED; - if ( !boot & pnpbios_dont_use_current_config ) + if ( !boot && pnpbios_dont_use_current_config ) return PNP_FUNCTION_NOT_SUPPORTED; status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0, nodenum, sizeof(char), data, 65536); @@ -350,7 +350,7 @@ static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node * u16 status; if (!pnp_bios_present()) return PNP_FUNCTION_NOT_SUPPORTED; - if ( !boot & pnpbios_dont_use_current_config ) + if ( !boot && pnpbios_dont_use_current_config ) return PNP_FUNCTION_NOT_SUPPORTED; status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0, data, 65536, 0, 0); diff --git a/drivers/serial/uart00.c b/drivers/serial/uart00.c index c5c4bfc1161c..deba4a10e439 100644 --- a/drivers/serial/uart00.c +++ b/drivers/serial/uart00.c @@ -235,8 +235,8 @@ static void uart00_modem_status(struct uart_port *port) status = UART_GET_MSR(port); - if (!status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK | - UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK)) + if (!(status & (UART_MSR_DCTS_MSK | UART_MSR_DDSR_MSK | + UART_MSR_TERI_MSK | UART_MSR_DDCD_MSK))) return; if (status & UART_MSR_DDCD_MSK) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 4b9cfc5e38b9..3fc167670230 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -456,7 +456,7 @@ void accel_clear_margins(struct vc_data *vc, struct display *p, region.color = attr_bgcol_ec(p, vc); region.rop = ROP_COPY; - if (rw & !bottom_only) { + if (rw && !bottom_only) { region.dx = info->var.xoffset + rs; region.dy = 0; region.width = rw; diff --git a/sound/oss/gus_midi.c b/sound/oss/gus_midi.c index 26d9a753cb20..18c2bb030867 100644 --- a/sound/oss/gus_midi.c +++ b/sound/oss/gus_midi.c @@ -179,7 +179,7 @@ static int gus_midi_buffer_status(int dev) qhead++; } spin_unlock_irqrestore(&lock,flags); - return (qlen > 0) | !(GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY); + return (qlen > 0) || !(GUS_MIDI_STATUS() & MIDI_XMIT_EMPTY); } #define MIDI_SYNTH_NAME "Gravis Ultrasound Midi" -- cgit v1.2.3 From 5b87896327ac878ea88ff2067dd4a7d5d13953a1 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 20 Mar 2003 06:01:46 -0800 Subject: [PATCH] cdrom buffer too small dvd_read_physical() uses a 20 char buffer to read in the dvd structure, however the size is really 4 bytes header + 17 bytes body so layer->bca ends up containing garbage. Kudos to the nice folks who made it a non multiple of 4 bytes. --- drivers/cdrom/cdrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index aea2bdce51b5..c2774d5224cc 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -1125,7 +1125,7 @@ static int dvd_do_auth(struct cdrom_device_info *cdi, dvd_authinfo *ai) static int dvd_read_physical(struct cdrom_device_info *cdi, dvd_struct *s) { - unsigned char buf[20], *base; + unsigned char buf[21], *base; struct dvd_layer *layer; struct cdrom_generic_command cgc; struct cdrom_device_ops *cdo = cdi->ops; -- cgit v1.2.3 From ea70003bf057d49cc84c08ea7dec776b4b0a0259 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:02:25 -0800 Subject: [PATCH] Amiga PCMCIA Ethernet clean up Amiga PCMCIA Ethernet: Use le16_to_cpus() instead of hardcoded byteswap (from Kars de Jong) --- drivers/net/apne.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/apne.c b/drivers/net/apne.c index b34302abf92b..7d9f45f7e2d9 100644 --- a/drivers/net/apne.c +++ b/drivers/net/apne.c @@ -111,9 +111,6 @@ static int init_pcmcia(void); #define MANUAL_HWADDR5 0x9a */ -#define WORDSWAP(a) ( (((a)>>8)&0xff) | ((a)<<8) ) - - static const char version[] = "apne.c:v1.1 7/10/98 Alain Malek (Alain.Malek@cryogen.ch)\n"; @@ -402,10 +399,9 @@ apne_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_pa } outb(ENISR_RDC, nic_base + NE_EN0_ISR); /* Ack intr. */ - - hdr->count = WORDSWAP(hdr->count); - ei_status.dmaing &= ~0x01; + + le16_to_cpus(&hdr->count); } /* Block input and output, similar to the Crynwr packet driver. If you -- cgit v1.2.3 From 84834c7d0b58a652acdac78947b9342e31377da6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:03:18 -0800 Subject: [PATCH] ADB: Fix spelling of sigprocmask ADB: Fix spelling of sigprocmask --- drivers/macintosh/adb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index a5a983fdbede..0f791c59ee52 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -249,7 +249,7 @@ adb_probe_task(void *x) strcpy(current->comm, "kadbprobe"); sigfillset(&blocked); - sicprocmask(SIG_BLOCK, &blocked, NULL); + sigprocmask(SIG_BLOCK, &blocked, NULL); flush_signals(current); printk(KERN_INFO "adb: starting probe task...\n"); -- cgit v1.2.3 From c0557225bed6a285a4d6043595055418eb03de4b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:03:27 -0800 Subject: [PATCH] M68k Apollo I/O updates M68k Apollo I/O updates for MMIO and pseudo-MMIO (ISA I/O after translation): - Use out_8() and out_be16() instead of outb() and outw() - Remove conflicting definitions of {in,out}[bw]() --- arch/m68k/apollo/dma.c | 3 ++- drivers/video/dnfb.c | 42 +++++++++++++++++++----------------------- include/asm-m68k/apollohw.h | 5 ----- 3 files changed, 21 insertions(+), 29 deletions(-) (limited to 'drivers') diff --git a/arch/m68k/apollo/dma.c b/arch/m68k/apollo/dma.c index 634e4367f557..36fbb08e31d7 100644 --- a/arch/m68k/apollo/dma.c +++ b/arch/m68k/apollo/dma.c @@ -10,6 +10,7 @@ #include #include #include +#include /* note only works for 16 Bit 1 page DMA's */ @@ -27,7 +28,7 @@ unsigned short dma_map_page(unsigned long phys_addr,int count,int type) { #if 0 printk("phys_addr: %x, page_aligned_addr: %x, start_map_addr: %x\n",phys_addr,page_aligned_addr,start_map_addr+i); #endif - outw(start_map_addr+i, xlat_map_entry); + out_be16(xlat_map_entry, start_map_addr+i); } next_free_xlat_entry+=2; diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c index 1809827e3af9..9d0a3e908771 100644 --- a/drivers/video/dnfb.c +++ b/drivers/video/dnfb.c @@ -103,11 +103,6 @@ #define SWAP(A) ((A>>8) | ((A&0xff) <<8)) -#if 0 -#define outb(a,d) *(char *)(a)=(d) -#define outw(a,d) *(unsigned short *)a=d -#endif - static struct fb_info fb_info; /* frame buffer operations */ @@ -147,9 +142,9 @@ static struct fb_fix_screeninfo dnfb_fix __initdata = { static int dnfb_blank(int blank, struct fb_info *info) { if (blank) - outb(0x0, AP_CONTROL_3A); + out_8(AP_CONTROL_3A, 0x0); else - outb(0x1, AP_CONTROL_3A); + out_8(AP_CONTROL_3A, 0x1); return 0; } @@ -175,8 +170,8 @@ void dnfb_copyarea(struct fb_info *info, struct fb_copyarea *area) x_word_count = (x_end >> 4) - (area->dx >> 4) + 1; start_mask = 0xffff0000 >> (area->dx & 0xf); end_mask = 0x7ffff >> (x_end & 0xf); - outb((((area->dx & 0xf) - (area->sx & 0xf)) % 16) | (0x4 << 5), - AP_CONTROL_0); + out_8(AP_CONTROL_0, + (((area->dx & 0xf) - (area->sx & 0xf)) % 16) | (0x4 << 5)); if ((area->dx & 0xf) < (area->sx & 0xf)) pre_read = 1; } else { @@ -185,15 +180,16 @@ void dnfb_copyarea(struct fb_info *info, struct fb_copyarea *area) x_word_count = (area->dx >> 4) - (x_end >> 4) + 1; start_mask = 0x7ffff >> (area->dx & 0xf); end_mask = 0xffff0000 >> (x_end & 0xf); - outb(((-((area->sx & 0xf) - (area->dx & 0xf))) % - 16) | (0x4 << 5), AP_CONTROL_0); + out_8(AP_CONTROL_0, + ((-((area->sx & 0xf) - (area->dx & 0xf))) % 16) | + (0x4 << 5)); if ((area->dx & 0xf) > (area->sx & 0xf)) pre_read = 1; } for (i = 0; i < area->height; i++) { - outb(0xc | (dest >> 16), AP_CONTROL_3A); + out_8(AP_CONTROL_3A, 0xc | (dest >> 16)); if (pre_read) { dummy = *src; @@ -201,11 +197,11 @@ void dnfb_copyarea(struct fb_info *info, struct fb_copyarea *area) } if (x_word_count) { - outb(start_mask, AP_WRITE_ENABLE); + out_8(AP_WRITE_ENABLE, start_mask); *src = dest; src += incr; dest += incr; - outb(0, AP_WRITE_ENABLE); + out_8(AP_WRITE_ENABLE, 0); for (j = 1; j < (x_word_count - 1); j++) { *src = dest; @@ -213,12 +209,12 @@ void dnfb_copyarea(struct fb_info *info, struct fb_copyarea *area) dest += incr; } - outb(start_mask, AP_WRITE_ENABLE); + out_8(AP_WRITE_ENABLE, start_mask); *src = dest; dest += incr; src += incr; } else { - outb(start_mask | end_mask, AP_WRITE_ENABLE); + out_8(AP_WRITE_ENABLE, start_mask | end_mask); *src = dest; dest += incr; src += incr; @@ -226,7 +222,7 @@ void dnfb_copyarea(struct fb_info *info, struct fb_copyarea *area) src += (y_delta / 16); dest += (y_delta / 16); } - outb(NORMAL_MODE, AP_CONTROL_0); + out_8(AP_CONTROL_0, NORMAL_MODE); } @@ -247,12 +243,12 @@ unsigned long __init dnfb_init(unsigned long mem_start) panic("unable to register apollo frame buffer\n"); /* now we have registered we can safely setup the hardware */ - outb(RESET_CREG, AP_CONTROL_3A); - outw(0x0, AP_WRITE_ENABLE); - outb(NORMAL_MODE, AP_CONTROL_0); - outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1); - outb(S_DATA_PLN, AP_CONTROL_2); - outw(SWAP(0x3), AP_ROP_1); + out_8(AP_CONTROL_3A, RESET_CREG); + out_be16(AP_WRITE_ENABLE, 0x0); + out_8(AP_CONTROL_0, NORMAL_MODE); + out_8(AP_CONTROL_1, (AD_BLT | DST_EQ_SRC | NORM_CREG1)); + out_8(AP_CONTROL_2, S_DATA_PLN); + out_be16(AP_ROP_1, SWAP(0x3)); printk("apollo frame buffer alive and kicking !\n"); return mem_start; diff --git a/include/asm-m68k/apollohw.h b/include/asm-m68k/apollohw.h index e12a638ca487..f29992a3927d 100644 --- a/include/asm-m68k/apollohw.h +++ b/include/asm-m68k/apollohw.h @@ -101,9 +101,4 @@ extern u_long timer_physaddr; #define isaIO2mem(x) (((((x) & 0x3f8) << 7) | (((x) & 0xfc00) >> 6) | ((x) & 0x7)) + 0x40000 + IO_BASE) -#define inb(addr) (*((volatile unsigned char *)(addr))) -#define outb(val,addr) (*((volatile unsigned char *)(addr)) = (val)) -#define inw(addr) (*((volatile unsigned short *)(addr))) -#define outw(val,addr) (*((volatile unsigned short *)(addr)) = (val)) - #endif -- cgit v1.2.3 From 1a2706b02ca537f94d4b8725644599b9b12c2a0f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:03:34 -0800 Subject: [PATCH] M68k gcc-3.2 warnings M68k: Kill warnings generated by gcc-3.2: - Add missing include - Move unused static data inside usage area - Kill deprecated multi-line string literals - Add semicolons to empty cases in switch() constructs - Comment out unused labels - Fix extra tokens at end of #endif directives - a3000_release() may not be optimized away - Kill uninitialized variable warning --- arch/m68k/amiga/amisound.c | 1 + arch/m68k/amiga/chipram.c | 1 + arch/m68k/apollo/config.c | 3 ++- arch/m68k/atari/ataints.c | 52 ++++++++++++++++++++++---------------------- arch/m68k/q40/q40ints.c | 4 +++- arch/m68k/sun3/sun3dvma.c | 2 +- drivers/scsi/a3000.c | 2 +- drivers/scsi/sun3_NCR5380.c | 4 ++-- include/asm-m68k/sun3-head.h | 2 +- include/asm-m68k/system.h | 5 ++++- 10 files changed, 42 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/arch/m68k/amiga/amisound.c b/arch/m68k/amiga/amisound.c index e18713237256..7b69717c7b9f 100644 --- a/arch/m68k/amiga/amisound.c +++ b/arch/m68k/amiga/amisound.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c index a680ffd4e190..dfb7b7cf348c 100644 --- a/arch/m68k/amiga/chipram.c +++ b/arch/m68k/amiga/chipram.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c index 5dae74f908f3..461aa796b808 100644 --- a/arch/m68k/apollo/config.c +++ b/arch/m68k/apollo/config.c @@ -48,7 +48,6 @@ static void dn_heartbeat(int on); static void dn_timer_int(int irq,void *, struct pt_regs *); static void (*sched_timer_handler)(int, void *, struct pt_regs *)=NULL; static void dn_get_model(char *model); -static int dn_cpuctrl=0xff00; static const char *apollo_models[] = { "DN3000 (Otter)", "DN3010 (Otter)", @@ -290,6 +289,8 @@ static void dn_get_model(char *model) } #ifdef CONFIG_HEARTBEAT +static int dn_cpuctrl=0xff00; + static void dn_heartbeat(int on) { if(on) { diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c index 80c45418188c..86f74f772917 100644 --- a/arch/m68k/atari/ataints.c +++ b/arch/m68k/atari/ataints.c @@ -273,29 +273,29 @@ asmlinkage void atari_prio_irq_handler( void ); /* Dummy function to allow asm with operands. */ void atari_fast_prio_irq_dummy (void) { __asm__ (__ALIGN_STR "\n" -"atari_fast_irq_handler: - orw #0x700,%%sr /* disable all interrupts */ -atari_prio_irq_handler:\t - addl %3,%2\n" /* preempt_count() += HARDIRQ_OFFSET */ - SAVE_ALL_INT "\n" - GET_CURRENT(%%d0) " +"atari_fast_irq_handler:\n\t" + "orw #0x700,%%sr\n" /* disable all interrupts */ +"atari_prio_irq_handler:\n\t" + "addl %3,%2\n\t" /* preempt_count() += HARDIRQ_OFFSET */ + SAVE_ALL_INT "\n\t" + GET_CURRENT(%%d0) "\n\t" /* get vector number from stack frame and convert to source */ - bfextu %%sp@(%c1){#4,#10},%%d0 - subw #(0x40-8),%%d0 - jpl 1f - addw #(0x40-8-0x18),%%d0 -1: lea %a0,%%a0 - addql #1,%%a0@(%%d0:l:4) - lea irq_handler,%%a0 - lea %%a0@(%%d0:l:8),%%a0 - pea %%sp@ /* push frame address */ - movel %%a0@(4),%%sp@- /* push handler data */ - movel %%d0,%%sp@- /* push int number */ - movel %%a0@,%%a0 - jsr %%a0@ /* and call the handler */ - addql #8,%%sp - addql #4,%%sp - jbra ret_from_interrupt" + "bfextu %%sp@(%c1){#4,#10},%%d0\n\t" + "subw #(0x40-8),%%d0\n\t" + "jpl 1f\n\t" + "addw #(0x40-8-0x18),%%d0\n" + "1:\tlea %a0,%%a0\n\t" + "addql #1,%%a0@(%%d0:l:4)\n\t" + "lea irq_handler,%%a0\n\t" + "lea %%a0@(%%d0:l:8),%%a0\n\t" + "pea %%sp@\n\t" /* push frame address */ + "movel %%a0@(4),%%sp@-\n\t" /* push handler data */ + "movel %%d0,%%sp@-\n\t" /* push int number */ + "movel %%a0@,%%a0\n\t" + "jsr %%a0@\n\t" /* and call the handler */ + "addql #8,%%sp\n\t" + "addql #4,%%sp\n\t" + "jbra ret_from_interrupt" : : "i" (&kstat_cpu(0).irqs), "n" (PT_OFF_FORMATVEC), "m" (preempt_count()), "di" (HARDIRQ_OFFSET) ); @@ -308,10 +308,10 @@ atari_prio_irq_handler:\t */ asmlinkage void falcon_hblhandler(void); asm(".text\n" -__ALIGN_STR "\n" -"falcon_hblhandler: - orw #0x200,%sp@ /* set saved ipl to 2 */ - rte"); +__ALIGN_STR "\n\t" +"falcon_hblhandler:\n\t" + "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */ + "rte"); /* Defined in entry.S; only increments 'num_spurious' */ asmlinkage void bad_interrupt(void); diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index 33285b663bc2..718d7a1da88d 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c @@ -127,6 +127,7 @@ int q40_request_irq(unsigned int irq, printk("warning IRQ 10 and 11 not distinguishable\n"); irq=10; default: + ; } if (irqCNTR = 0; diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 7ab4086e6f26..90ec7b11f7ec 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -1217,8 +1217,8 @@ static void NCR5380_dma_complete( struct Scsi_Host *instance ) BASR_ACK)) == (BASR_PHASE_MATCH | BASR_ACK)) { printk("scsi%d: BASR %02x\n", HOSTNO, NCR5380_read(BUS_AND_STATUS_REG)); - printk("scsi%d: bus stuck in data phase -- probably a - single byte overrun!\n", HOSTNO); + printk("scsi%d: bus stuck in data phase -- probably a single byte " + "overrun!\n", HOSTNO); printk("not prepared for this error!\n"); printk("please e-mail sammy@sammy.net with a description of how this\n"); printk("error was produced.\n"); diff --git a/include/asm-m68k/sun3-head.h b/include/asm-m68k/sun3-head.h index d2c9f39da8fc..f799d95bad53 100644 --- a/include/asm-m68k/sun3-head.h +++ b/include/asm-m68k/sun3-head.h @@ -9,4 +9,4 @@ #define FC_SUPERD 5 #define FC_CPU 7 -#endif __SUN3_HEAD_H +#endif /* __SUN3_HEAD_H */ diff --git a/include/asm-m68k/system.h b/include/asm-m68k/system.h index 112ea2a6a047..77ac69c31981 100644 --- a/include/asm-m68k/system.h +++ b/include/asm-m68k/system.h @@ -101,21 +101,24 @@ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int siz case 1: tmp = *(u8 *)ptr; *(u8 *)ptr = x; + x = tmp; break; case 2: tmp = *(u16 *)ptr; *(u16 *)ptr = x; + x = tmp; break; case 4: tmp = *(u32 *)ptr; *(u32 *)ptr = x; + x = tmp; break; default: BUG(); } local_irq_restore(flags); - return tmp; + return x; } #else static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size) -- cgit v1.2.3 From 430805cba89d1fd1339c65afd63d57fa34fa6ea0 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:03:57 -0800 Subject: [PATCH] WD33c93 missing export Wd33c93 SCSI: Export wd33c93_proc_info (needed for Amiga A3000, A2091, and GVP II SCSI, and for MVME147 SCSI). --- drivers/scsi/wd33c93.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index f9cb9e3c8d1e..04c7d3907242 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -2086,3 +2086,4 @@ EXPORT_SYMBOL(wd33c93_release); EXPORT_SYMBOL(wd33c93_abort); EXPORT_SYMBOL(wd33c93_queuecommand); EXPORT_SYMBOL(wd33c93_intr); +EXPORT_SYMBOL(wd33c93_proc_info); -- cgit v1.2.3 From d63ffc2238026b83f2df1808682f774cd40f1c8e Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:04:05 -0800 Subject: [PATCH] M68k net warnings M68k net drivers: Kill warnings caused by implicit conversions from volatile * --- drivers/net/82596.c | 6 +++--- drivers/net/macmace.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/82596.c b/drivers/net/82596.c index 76bf501617bd..28001ae6c1b3 100644 --- a/drivers/net/82596.c +++ b/drivers/net/82596.c @@ -646,7 +646,7 @@ static int init_i596_mem(struct net_device *dev) /* change the scp address */ - MPU_PORT(dev, PORT_ALTSCP, (void *)virt_to_bus(&lp->scp)); + MPU_PORT(dev, PORT_ALTSCP, (void *)virt_to_bus((void *)&lp->scp)); #elif defined(ENABLE_APRICOT) @@ -677,8 +677,8 @@ static int init_i596_mem(struct net_device *dev) lp->scp.sysbus = 0x00440000; #endif - lp->scp.iscp = WSWAPiscp(virt_to_bus(&(lp->iscp))); - lp->iscp.scb = WSWAPscb(virt_to_bus(&(lp->scb))); + lp->scp.iscp = WSWAPiscp(virt_to_bus((void *)&lp->iscp)); + lp->iscp.scb = WSWAPscb(virt_to_bus((void *)&lp->scb)); lp->iscp.stat = ISCP_BUSY; lp->cmd_backlog = 0; diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c index 4e8a08b78804..a99f7d037d0a 100644 --- a/drivers/net/macmace.c +++ b/drivers/net/macmace.c @@ -331,8 +331,8 @@ static int mace_open(struct net_device *dev) return -ENOMEM; } - mp->rx_ring_phys = (unsigned char *) virt_to_bus(mp->rx_ring); - mp->tx_ring_phys = (unsigned char *) virt_to_bus(mp->tx_ring); + mp->rx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->rx_ring); + mp->tx_ring_phys = (unsigned char *) virt_to_bus((void *)mp->tx_ring); /* We want the Rx buffer to be uncached and the Tx buffer to be writethrough */ -- cgit v1.2.3 From c7fc8da091724df52f6e13453d2f344e79a58c1a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:04:14 -0800 Subject: [PATCH] M68k SCSI warnings M68k SCSI drivers: Kill warnings caused by implicit conversions from volatile * and remove some unneeded casts --- drivers/scsi/53c7xx.c | 4 ++-- drivers/scsi/blz1230.c | 4 ++-- drivers/scsi/blz2060.c | 4 ++-- drivers/scsi/cyberstorm.c | 4 ++-- drivers/scsi/cyberstormII.c | 4 ++-- drivers/scsi/fastlane.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c index 7fd1ccaffd2d..799dad164ba9 100644 --- a/drivers/scsi/53c7xx.c +++ b/drivers/scsi/53c7xx.c @@ -1463,9 +1463,9 @@ NCR53c7x0_init_fixup (struct Scsi_Host *host) { patch_abs_32 (hostdata->script, 0, test_src, virt_to_bus(&hostdata->test_source)); patch_abs_32 (hostdata->script, 0, saved_dsa, - virt_to_bus(&hostdata->saved2_dsa)); + virt_to_bus((void *)&hostdata->saved2_dsa)); patch_abs_32 (hostdata->script, 0, emulfly, - virt_to_bus(&hostdata->emulated_intfly)); + virt_to_bus((void *)&hostdata->emulated_intfly)); patch_abs_rwri_data (hostdata->script, 0, dsa_check_reselect, (unsigned char)(Ent_dsa_code_check_reselect - Ent_dsa_zero)); diff --git a/drivers/scsi/blz1230.c b/drivers/scsi/blz1230.c index 57296ffd25af..1fb8cd9890cf 100644 --- a/drivers/scsi/blz1230.c +++ b/drivers/scsi/blz1230.c @@ -167,8 +167,8 @@ int __init blz1230_esp_detect(Scsi_Host_Template *tpnt) esp->eregs = eregs; /* Set the command buffer */ - esp->esp_command = (volatile unsigned char*) cmd_buffer; - esp->esp_command_dvma = virt_to_bus(cmd_buffer); + esp->esp_command = cmd_buffer; + esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; esp->slot = board+REAL_BLZ1230_ESP_ADDR; diff --git a/drivers/scsi/blz2060.c b/drivers/scsi/blz2060.c index 07a9220816a3..77f77e9cefdb 100644 --- a/drivers/scsi/blz2060.c +++ b/drivers/scsi/blz2060.c @@ -142,8 +142,8 @@ int __init blz2060_esp_detect(Scsi_Host_Template *tpnt) esp->eregs = (struct ESP_regs *)(address + BLZ2060_ESP_ADDR); /* Set the command buffer */ - esp->esp_command = (volatile unsigned char*) cmd_buffer; - esp->esp_command_dvma = virt_to_bus(cmd_buffer); + esp->esp_command = cmd_buffer; + esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; request_irq(IRQ_AMIGA_PORTS, esp_intr, SA_SHIRQ, diff --git a/drivers/scsi/cyberstorm.c b/drivers/scsi/cyberstorm.c index 83a3a0a9e5da..e795eeb78629 100644 --- a/drivers/scsi/cyberstorm.c +++ b/drivers/scsi/cyberstorm.c @@ -168,8 +168,8 @@ int __init cyber_esp_detect(Scsi_Host_Template *tpnt) esp->eregs = (struct ESP_regs *)(address + CYBER_ESP_ADDR); /* Set the command buffer */ - esp->esp_command = (volatile unsigned char*) cmd_buffer; - esp->esp_command_dvma = virt_to_bus(cmd_buffer); + esp->esp_command = cmd_buffer; + esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; request_irq(IRQ_AMIGA_PORTS, esp_intr, SA_SHIRQ, diff --git a/drivers/scsi/cyberstormII.c b/drivers/scsi/cyberstormII.c index 25eb423ce467..4d0bf3ed1456 100644 --- a/drivers/scsi/cyberstormII.c +++ b/drivers/scsi/cyberstormII.c @@ -149,8 +149,8 @@ int __init cyberII_esp_detect(Scsi_Host_Template *tpnt) esp->eregs = eregs; /* Set the command buffer */ - esp->esp_command = (volatile unsigned char*) cmd_buffer; - esp->esp_command_dvma = virt_to_bus(cmd_buffer); + esp->esp_command = cmd_buffer; + esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; request_irq(IRQ_AMIGA_PORTS, esp_intr, SA_SHIRQ, diff --git a/drivers/scsi/fastlane.c b/drivers/scsi/fastlane.c index b58c0289ea14..62a473c3497e 100644 --- a/drivers/scsi/fastlane.c +++ b/drivers/scsi/fastlane.c @@ -191,8 +191,8 @@ int __init fastlane_esp_detect(Scsi_Host_Template *tpnt) esp->edev = (void *) address; /* Set the command buffer */ - esp->esp_command = (volatile unsigned char*) cmd_buffer; - esp->esp_command_dvma = virt_to_bus(cmd_buffer); + esp->esp_command = cmd_buffer; + esp->esp_command_dvma = virt_to_bus((void *)cmd_buffer); esp->irq = IRQ_AMIGA_PORTS; esp->slot = board+FASTLANE_ESP_ADDR; -- cgit v1.2.3 From 081448119c6d748605a05b237f48040bcfaa4f0a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:04:21 -0800 Subject: [PATCH] M68k NCR5380 SCSI updates M68k NCR5380 SCSI updates for changes in SCSI and NCR5380 SCSI layers: - Sun-3/3x (from Sam Creasey) - Atari (ported updates from Sun-3) - Mac (ported updates from Sun-3) --- drivers/scsi/atari_NCR5380.c | 17 +++++++---------- drivers/scsi/atari_scsi.c | 8 ++++---- drivers/scsi/atari_scsi.h | 2 -- drivers/scsi/mac_NCR5380.c | 23 +++++++++-------------- drivers/scsi/sun3_NCR5380.c | 15 ++++++++------- drivers/scsi/sun3_scsi.c | 6 ++++-- drivers/scsi/sun3_scsi.h | 4 ++-- drivers/scsi/sun3_scsi_vme.c | 6 +++--- drivers/scsi/sun3x_esp.c | 33 +++++++++++++++++++++++++++++++++ 9 files changed, 70 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index df9da107d11b..a5ce400cd2d9 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -834,7 +834,7 @@ lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) * */ -static void __init NCR5380_init (struct Scsi_Host *instance, int flags) +static int NCR5380_init (struct Scsi_Host *instance, int flags) { int i; SETUP_HOSTDATA(instance); @@ -878,6 +878,8 @@ static void __init NCR5380_init (struct Scsi_Host *instance, int flags) NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0); + + return 0; } /* @@ -898,10 +900,7 @@ static void __init NCR5380_init (struct Scsi_Host *instance, int flags) * */ -/* Only make static if a wrapper function is used */ -#ifndef NCR5380_queue_command static -#endif int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) { SETUP_HOSTDATA(cmd->host); @@ -1014,7 +1013,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) if (in_interrupt() || ((flags >> 8) & 7) >= 6) queue_main(); else - NCR5380_main(); + NCR5380_main(NULL); return 0; } @@ -1030,7 +1029,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) * reenable them. This prevents reentrancy and kernel stack overflow. */ -static void NCR5380_main (void) +static void NCR5380_main (void *bl) { Scsi_Cmnd *tmp, *prev; struct Scsi_Host *instance = first_instance; @@ -2642,9 +2641,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) * called where the loop started in NCR5380_main(). */ -#ifndef NCR5380_abort static -#endif int NCR5380_abort (Scsi_Cmnd *cmd) { struct Scsi_Host *instance = cmd->host; @@ -2842,7 +2839,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd) /* - * Function : int NCR5380_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) + * Function : int NCR5380_reset (Scsi_Cmnd *cmd) * * Purpose : reset the SCSI bus. * @@ -2850,7 +2847,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd) * */ -static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags) +static int NCR5380_bus_reset( Scsi_Cmnd *cmd) { SETUP_HOSTDATA(cmd->host); int i; diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 07c40bd87e67..25412b60a3e7 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -819,7 +819,7 @@ void __init atari_scsi_setup(char *str, int *ints) #endif } -int atari_scsi_reset( Scsi_Cmnd *cmd, unsigned int reset_flags) +int atari_scsi_bus_reset(Scsi_Cmnd *cmd) { int rv; struct NCR5380_hostdata *hostdata = @@ -845,7 +845,7 @@ int atari_scsi_reset( Scsi_Cmnd *cmd, unsigned int reset_flags) #endif /* REAL_DMA */ } - rv = NCR5380_reset(cmd, reset_flags); + rv = NCR5380_bus_reset(cmd); /* Re-enable ints */ if (IS_A_TT()) { @@ -1146,8 +1146,8 @@ static Scsi_Host_Template driver_template = { .release = atari_scsi_release, .info = atari_scsi_info, .queuecommand = atari_scsi_queue_command, - .abort = atari_scsi_abort, - .reset = atari_scsi_reset, + .eh_abort_handler = atari_scsi_abort, + .eh_bus_reset_handler = atari_scsi_bus_reset, .can_queue = 0, /* initialized at run-time */ .this_id = 0, /* initialized at run-time */ .sg_tablesize = 0, /* initialized at run-time */ diff --git a/drivers/scsi/atari_scsi.h b/drivers/scsi/atari_scsi.h index a6fd05a74d33..b417d6c6880c 100644 --- a/drivers/scsi/atari_scsi.h +++ b/drivers/scsi/atari_scsi.h @@ -18,10 +18,8 @@ /* (I_HAVE_OVERRUNS stuff removed) */ #ifndef ASM -int atari_scsi_abort (Scsi_Cmnd *); int atari_scsi_detect (Scsi_Host_Template *); const char *atari_scsi_info (struct Scsi_Host *); -int atari_scsi_queue_command (Scsi_Cmnd *, void (*done) (Scsi_Cmnd *)); int atari_scsi_reset (Scsi_Cmnd *, unsigned int); int atari_scsi_proc_info (char *, char **, off_t, int, int, int); #ifdef MODULE diff --git a/drivers/scsi/mac_NCR5380.c b/drivers/scsi/mac_NCR5380.c index b51eda3f8110..81e94a695e5e 100644 --- a/drivers/scsi/mac_NCR5380.c +++ b/drivers/scsi/mac_NCR5380.c @@ -850,7 +850,7 @@ lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) /* - * Function : void NCR5380_init (struct Scsi_Host *instance) + * Function : void NCR5380_init (struct Scsi_Host *instance, int flags) * * Purpose : initializes *instance and corresponding 5380 chip. * @@ -861,7 +861,7 @@ lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) * */ -static void NCR5380_init (struct Scsi_Host *instance, int flags) +static int NCR5380_init (struct Scsi_Host *instance, int flags) { int i; SETUP_HOSTDATA(instance); @@ -905,6 +905,8 @@ static void NCR5380_init (struct Scsi_Host *instance, int flags) NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0); + + return 0; } /* @@ -925,17 +927,13 @@ static void NCR5380_init (struct Scsi_Host *instance, int flags) * */ -/* Only make static if a wrapper function is used */ -#ifndef NCR5380_queue_command static -#endif int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) { SETUP_HOSTDATA(cmd->host); Scsi_Cmnd *tmp; int oldto; unsigned long flags; - extern int update_timeout(Scsi_Cmnd * SCset, int timeout); #if (NDEBUG & NDEBUG_NO_WRITE) switch (cmd->cmnd[0]) { @@ -1025,12 +1023,12 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) if (in_interrupt() > 0 || ((flags >> 8) & 7) >= 6) queue_main(); else - NCR5380_main(); + NCR5380_main(NULL); return 0; } /* - * Function : NCR5380_main (void) + * Function : NCR5380_main (void *bl) * * Purpose : NCR5380_main is a coroutine that runs as long as more work can * be done on the NCR5380 host adapters in a system. Both @@ -1041,7 +1039,7 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) * reenable them. This prevents reentrancy and kernel stack overflow. */ -static void NCR5380_main (void) +static void NCR5380_main (void *bl) { Scsi_Cmnd *tmp, *prev; struct Scsi_Host *instance = first_instance; @@ -2790,9 +2788,6 @@ static void NCR5380_reselect (struct Scsi_Host *instance) * called where the loop started in NCR5380_main(). */ -#ifndef NCR5380_abort -static -#endif int NCR5380_abort (Scsi_Cmnd *cmd) { struct Scsi_Host *instance = cmd->host; @@ -2982,7 +2977,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd) /* - * Function : int NCR5380_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) + * Function : int NCR5380_bus_reset (Scsi_Cmnd *cmd) * * Purpose : reset the SCSI bus. * @@ -2990,7 +2985,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd) * */ -static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags) +static int NCR5380_bus_reset( Scsi_Cmnd *cmd) { SETUP_HOSTDATA(cmd->host); int i; diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 90ec7b11f7ec..cfcfb247fd2b 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -842,7 +842,7 @@ lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) * */ -static void __init NCR5380_init (struct Scsi_Host *instance, int flags) +static int NCR5380_init (struct Scsi_Host *instance, int flags) { int i; SETUP_HOSTDATA(instance); @@ -886,6 +886,8 @@ static void __init NCR5380_init (struct Scsi_Host *instance, int flags) NCR5380_write(MODE_REG, MR_BASE); NCR5380_write(TARGET_COMMAND_REG, 0); NCR5380_write(SELECT_ENABLE_REG, 0); + + return 0; } /* @@ -912,7 +914,6 @@ static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) SETUP_HOSTDATA(cmd->host); Scsi_Cmnd *tmp; unsigned long flags; - extern int update_timeout(Scsi_Cmnd * SCset, int timeout); #if (NDEBUG & NDEBUG_NO_WRITE) switch (cmd->cmnd[0]) { @@ -1014,7 +1015,7 @@ static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) if (in_interrupt() || ((flags >> 8) & 7) >= 6) queue_main(); else - NCR5380_main(); + NCR5380_main(NULL); return 0; } @@ -1030,7 +1031,7 @@ static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) * reenable them. This prevents reentrancy and kernel stack overflow. */ -static void NCR5380_main (void) +static void NCR5380_main (void *bl) { Scsi_Cmnd *tmp, *prev; struct Scsi_Host *instance = first_instance; @@ -1065,7 +1066,7 @@ static void NCR5380_main (void) local_save_flags(flags); do { - local_irq_disable(flags); /* Freeze request queues */ + local_irq_disable(); /* Freeze request queues */ done = 1; if (!hostdata->connected) { @@ -2868,7 +2869,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) /* - * Function : int NCR5380_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) + * Function : int NCR5380_bus_reset (Scsi_Cmnd *cmd) * * Purpose : reset the SCSI bus. * @@ -2876,7 +2877,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) * */ -static int NCR5380_reset( Scsi_Cmnd *cmd, unsigned int reset_flags) +static int NCR5380_bus_reset( Scsi_Cmnd *cmd) { SETUP_HOSTDATA(cmd->host); int i; diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 978e81e9e602..9ca0a90026a8 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -79,6 +79,8 @@ #include "sun3_scsi.h" #include "NCR5380.h" +static void NCR5380_print(struct Scsi_Host *instance); + /* #define OLDDMA */ #define USE_WRAPPER @@ -621,8 +623,8 @@ static Scsi_Host_Template driver_template = { .release = sun3scsi_release, .info = sun3scsi_info, .queuecommand = sun3scsi_queue_command, - .abort = sun3scsi_abort, - .reset = sun3scsi_reset, + .eh_abort_handler = sun3scsi_abort, + .eh_bus_reset_handler = sun3scsi_bus_reset, .can_queue = CAN_QUEUE, .this_id = 7, .sg_tablesize = SG_TABLESIZE, diff --git a/drivers/scsi/sun3_scsi.h b/drivers/scsi/sun3_scsi.h index b7a569b3d2bb..23a897d39c87 100644 --- a/drivers/scsi/sun3_scsi.h +++ b/drivers/scsi/sun3_scsi.h @@ -55,7 +55,7 @@ static int sun3scsi_abort (Scsi_Cmnd *); static int sun3scsi_detect (Scsi_Host_Template *); static const char *sun3scsi_info (struct Scsi_Host *); -static int sun3scsi_reset(Scsi_Cmnd *, unsigned int); +static int sun3scsi_bus_reset(Scsi_Cmnd *); static int sun3scsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *)); static int sun3scsi_proc_info (char *buffer, char **start, off_t offset, int length, int hostno, int inout); @@ -109,7 +109,7 @@ static int sun3scsi_release (struct Scsi_Host *); #define NCR5380_intr sun3scsi_intr #define NCR5380_queue_command sun3scsi_queue_command -#define NCR5380_reset sun3scsi_reset +#define NCR5380_bus_reset sun3scsi_bus_reset #define NCR5380_abort sun3scsi_abort #define NCR5380_proc_info sun3scsi_proc_info #define NCR5380_dma_xfer_len(i, cmd, phase) \ diff --git a/drivers/scsi/sun3_scsi_vme.c b/drivers/scsi/sun3_scsi_vme.c index 056a65cd4551..484500e20395 100644 --- a/drivers/scsi/sun3_scsi_vme.c +++ b/drivers/scsi/sun3_scsi_vme.c @@ -1,4 +1,4 @@ -/* + /* * Sun3 SCSI stuff by Erik Verbruggen (erik@bigmama.xtdnet.nl) * * Sun3 DMA routines added by Sam Creasey (sammy@sammy.net) @@ -566,8 +566,8 @@ static Scsi_Host_Template driver_template = { .release = sun3scsi_release, .info = sun3scsi_info, .queuecommand = sun3scsi_queue_command, - .abort = sun3scsi_abort, - .reset = sun3scsi_reset, + .eh_abort_handler = sun3scsi_abort, + .eh_bus_reset_handler = sun3scsi_bus_reset, .can_queue = CAN_QUEUE, .this_id = 7, .sg_tablesize = SG_TABLESIZE, diff --git a/drivers/scsi/sun3x_esp.c b/drivers/scsi/sun3x_esp.c index bfbdf74c018b..7c44fc01f784 100644 --- a/drivers/scsi/sun3x_esp.c +++ b/drivers/scsi/sun3x_esp.c @@ -374,11 +374,44 @@ static void dma_advance_sg (Scsi_Cmnd *sp) sp->SCp.ptr = (char *)((unsigned long)sp->SCp.buffer->dvma_address); } + +static int esp_slave_alloc(Scsi_Device *SDptr) +{ + struct esp_device *esp_dev = + kmalloc(sizeof(struct esp_device), GFP_ATOMIC); + + if (!esp_dev) + return -ENOMEM; + memset(esp_dev, 0, sizeof(struct esp_device)); + SDptr->hostdata = esp_dev; + return 0; +} + +static void esp_slave_destroy(Scsi_Device *SDptr) +{ + struct NCR_ESP *esp = (struct NCR_ESP *) SDptr->host->hostdata; + + esp->targets_present &= ~(1 << SDptr->id); + kfree(SDptr->hostdata); + SDptr->hostdata = NULL; +} + + +static int sun3x_esp_release(struct Scsi_Host *instance) +{ + /* this code does not support being compiled as a module */ + return 1; + +} + static Scsi_Host_Template driver_template = { .proc_name = "esp", .proc_info = &esp_proc_info, .name = "Sun ESP 100/100a/200", .detect = sun3x_esp_detect, + .release = sun3x_esp_release, + .slave_alloc = esp_slave_alloc, + .slave_destroy = esp_slave_destroy, .info = esp_info, .command = esp_command, .queuecommand = esp_queue, -- cgit v1.2.3 From 50d21c5c175593d06021b7950557622a3f88f363 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:04:29 -0800 Subject: [PATCH] Amiga serial updates Convert Amiga serial driver to use tasklets (from Roman Zippel) --- drivers/char/amiserial.c | 25 +++++-------------------- include/linux/serialP.h | 2 ++ 2 files changed, 7 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 9978844a3bc4..37cbc60df1a6 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -102,8 +102,6 @@ static char *serial_version = "4.30"; static char *serial_name = "Amiga-builtin serial driver"; -static DECLARE_TASK_QUEUE(tq_serial); - static struct tty_driver serial_driver, callout_driver; static int serial_refcount; @@ -276,8 +274,7 @@ static _INLINE_ void rs_sched_event(struct async_struct *info, int event) { info->event |= 1 << event; - queue_task(&info->tqueue, &tq_serial); - mark_bh(SERIAL_BH); + tasklet_schedule(&info->tlet); } static _INLINE_ void receive_chars(struct async_struct *info) @@ -560,12 +557,8 @@ static void ser_tx_int(int irq, void *dev_id, struct pt_regs * regs) * interrupt driver proper are done; the interrupt driver schedules * them using rs_sched_event(), and they get done here. */ -static void do_serial_bh(void) -{ - run_task_queue(&tq_serial); -} -static void do_softint(void *private_) +static void do_softint(unsigned long private_) { struct async_struct *info = (struct async_struct *) private_; struct tty_struct *tty; @@ -1878,8 +1871,7 @@ static int get_async_struct(int line, struct async_struct **ret_info) info->flags = sstate->flags; info->xmit_fifo_size = sstate->xmit_fifo_size; info->line = line; - info->tqueue.routine = do_softint; - info->tqueue.data = info; + tasklet_init(&info->tlet, do_softint, (unsigned long)info); info->state = sstate; if (sstate->info) { kfree(info); @@ -2117,8 +2109,6 @@ static int __init rs_init(void) if (!request_mem_region(CUSTOM_PHYSADDR+0x30, 4, "amiserial [Paula]")) return -EBUSY; - init_bh(SERIAL_BH, do_serial_bh); - IRQ_ports = NULL; show_serial_version(); @@ -2234,23 +2224,18 @@ static int __init rs_init(void) static __exit void rs_exit(void) { - unsigned long flags; int e1, e2; - struct async_struct *info; + struct async_struct *info = rs_table[0].info; /* printk("Unloading %s: version %s\n", serial_name, serial_version); */ - save_flags(flags); - cli(); - remove_bh(SERIAL_BH); + tasklet_kill(&info->tlet); if ((e1 = tty_unregister_driver(&serial_driver))) printk("SERIAL: failed to unregister serial driver (%d)\n", e1); if ((e2 = tty_unregister_driver(&callout_driver))) printk("SERIAL: failed to unregister callout driver (%d)\n", e2); - restore_flags(flags); - info = rs_table[0].info; if (info) { rs_table[0].info = NULL; kfree(info); diff --git a/include/linux/serialP.h b/include/linux/serialP.h index 73541f600528..eb81e4e9b181 100644 --- a/include/linux/serialP.h +++ b/include/linux/serialP.h @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #if (LINUX_VERSION_CODE < 0x020300) @@ -87,6 +88,7 @@ struct async_struct { u16 iomem_reg_shift; int io_type; struct work_struct work; + struct tasklet_struct tlet; #ifdef DECLARE_WAITQUEUE wait_queue_head_t open_wait; wait_queue_head_t close_wait; -- cgit v1.2.3 From 55a248c708cb570ed1e35e24432422510ed3e4a3 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:04:36 -0800 Subject: [PATCH] Genrtc updates Genrtc: Sync generic RTC driver with 2.4.x. --- drivers/char/genrtc.c | 81 +++++++++++++++++++++++++++----------------------- include/asm-m68k/rtc.h | 12 ++++---- include/linux/rtc.h | 3 +- 3 files changed, 51 insertions(+), 45 deletions(-) (limited to 'drivers') diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 6be546513a3c..0de5b2d8e51d 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c @@ -1,5 +1,8 @@ /* - * Real Time Clock interface for q40 and other m68k machines + * Real Time Clock interface for + * - q40 and other m68k machines, + * - HP PARISC machines + * - PowerPC machines * emulate some RTC irq capabilities in software * * Copyright (C) 1999 Richard Zidlicky @@ -13,7 +16,7 @@ * pseudo-file for status information. * * The ioctls can be used to set the interrupt behaviour where - * supported. + * supported. * * The /dev/rtc interface will block on reads until an interrupt * has been received. If a RTC interrupt has already happened, @@ -34,9 +37,10 @@ * 1.04 removed useless timer code rz@linux-m68k.org * 1.05 portable RTC_UIE emulation rz@linux-m68k.org * 1.06 set_rtc_time can return an error trini@kernel.crashing.org + * 1.07 ported to HP PARISC (hppa) Helge Deller */ -#define RTC_VERSION "1.06" +#define RTC_VERSION "1.07" #include #include @@ -63,20 +67,17 @@ static DECLARE_WAIT_QUEUE_HEAD(gen_rtc_wait); -static int gen_rtc_ioctl(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg); - /* * Bits in gen_rtc_status. */ #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ -unsigned char gen_rtc_status; /* bitmapped status byte. */ -unsigned long gen_rtc_irq_data; /* our output to the world */ +static unsigned char gen_rtc_status; /* bitmapped status byte. */ +static unsigned long gen_rtc_irq_data; /* our output to the world */ /* months start at 0 now */ -unsigned char days_in_mo[] = +static unsigned char days_in_mo[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; static int irq_active; @@ -89,18 +90,20 @@ static unsigned int oldsecs; static int lostint; static int tt_exp; -void gen_rtc_timer(unsigned long data); +static void gen_rtc_timer(unsigned long data); static volatile int stask_active; /* schedule_work */ static volatile int ttask_active; /* timer_task */ static int stop_rtc_timers; /* don't requeue tasks */ static spinlock_t gen_rtc_lock = SPIN_LOCK_UNLOCKED; +static void gen_rtc_interrupt(unsigned long arg); + /* * Routine to poll RTC seconds field for change as often as possible, * after first RTC_UIE use timer to reduce polling */ -void genrtc_troutine(void *data) +static void genrtc_troutine(void *data) { unsigned int tmp = get_rtc_ss(); @@ -124,7 +127,7 @@ void genrtc_troutine(void *data) stask_active = 0; } -void gen_rtc_timer(unsigned long data) +static void gen_rtc_timer(unsigned long data) { lostint = get_rtc_ss() - oldsecs ; if (lostint<0) @@ -145,7 +148,7 @@ void gen_rtc_timer(unsigned long data) * from some routine that periodically (eg 100HZ) monitors * whether RTC_SECS changed */ -void gen_rtc_interrupt(unsigned long arg) +static void gen_rtc_interrupt(unsigned long arg) { /* We store the status in the low byte and the number of * interrupts received since the last read in the remainder @@ -175,7 +178,7 @@ static ssize_t gen_rtc_read(struct file *file, char *buf, unsigned long data; ssize_t retval; - if (count != sizeof (unsigned int) && count != sizeof (unsigned long)) + if (count != sizeof (unsigned int) && count != sizeof (unsigned long)) return -EINVAL; if (file->f_flags & O_NONBLOCK && !gen_rtc_irq_data) @@ -385,24 +388,24 @@ static int gen_rtc_read_proc(char *page, char **start, off_t off, */ static struct file_operations gen_rtc_fops = { - .owner = THIS_MODULE, + .owner = THIS_MODULE, #ifdef CONFIG_GEN_RTC_X - .read = gen_rtc_read, - .poll = gen_rtc_poll, + .read = gen_rtc_read, + .poll = gen_rtc_poll, #endif - .ioctl = gen_rtc_ioctl, - .open = gen_rtc_open, - .release = gen_rtc_release + .ioctl = gen_rtc_ioctl, + .open = gen_rtc_open, + .release = gen_rtc_release, }; static struct miscdevice rtc_gen_dev = { - RTC_MINOR, - "rtc", - &gen_rtc_fops + .minor = RTC_MINOR, + .name = "rtc", + .fops = &gen_rtc_fops, }; -int __init rtc_generic_init(void) +static int __init rtc_generic_init(void) { int retval; @@ -436,16 +439,18 @@ module_exit(rtc_generic_exit); * Info exported via "/proc/rtc". */ -int gen_rtc_proc_output(char *buf) +#ifdef CONFIG_PROC_FS + +static int gen_rtc_proc_output(char *buf) { char *p; struct rtc_time tm; - unsigned tmp; + unsigned int flags; struct rtc_pll_info pll; p = buf; - get_rtc_time(&tm); + flags = get_rtc_time(&tm); p += sprintf(p, "rtc_time\t: %02d:%02d:%02d\n" @@ -454,7 +459,7 @@ int gen_rtc_proc_output(char *buf) tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, 1900); - tm.tm_hour=0;tm.tm_min=0;tm.tm_sec=0; + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; p += sprintf(p, "alarm\t\t: "); if (tm.tm_hour <= 24) @@ -472,7 +477,6 @@ int gen_rtc_proc_output(char *buf) else p += sprintf(p, "**\n"); - tmp= RTC_24H ; p += sprintf(p, "DST_enable\t: %s\n" "BCD\t\t: %s\n" @@ -483,15 +487,15 @@ int gen_rtc_proc_output(char *buf) "periodic_IRQ\t: %s\n" "periodic_freq\t: %ld\n" "batt_status\t: %s\n", - (tmp & RTC_DST_EN) ? "yes" : "no", - (tmp & RTC_DM_BINARY) ? "no" : "yes", - (tmp & RTC_24H) ? "yes" : "no", - (tmp & RTC_SQWE) ? "yes" : "no", - (tmp & RTC_AIE) ? "yes" : "no", + (flags & RTC_DST_EN) ? "yes" : "no", + (flags & RTC_DM_BINARY) ? "no" : "yes", + (flags & RTC_24H) ? "yes" : "no", + (flags & RTC_SQWE) ? "yes" : "no", + (flags & RTC_AIE) ? "yes" : "no", irq_active ? "yes" : "no", - (tmp & RTC_PIE) ? "yes" : "no", + (flags & RTC_PIE) ? "yes" : "no", 0L /* freq */, - "okay" ); + (flags & RTC_BATT_BAD) ? "bad" : "okay"); if (!get_rtc_pll(&pll)) p += sprintf(p, "PLL adjustment\t: %d\n" @@ -506,7 +510,7 @@ int gen_rtc_proc_output(char *buf) pll.pll_posmult, pll.pll_negmult, pll.pll_clock); - return p - buf; + return p - buf; } static int gen_rtc_read_proc(char *page, char **start, off_t off, @@ -521,6 +525,9 @@ static int gen_rtc_read_proc(char *page, char **start, off_t off, return len; } +#endif /* CONFIG_PROC_FS */ + MODULE_AUTHOR("Richard Zidlicky"); MODULE_LICENSE("GPL"); + diff --git a/include/asm-m68k/rtc.h b/include/asm-m68k/rtc.h index 043d5f947618..2de18f80a563 100644 --- a/include/asm-m68k/rtc.h +++ b/include/asm-m68k/rtc.h @@ -14,23 +14,21 @@ #ifdef __KERNEL__ #include +#include #include -/* a few implementation details for the emulation : */ - #define RTC_PIE 0x40 /* periodic interrupt enable */ #define RTC_AIE 0x20 /* alarm interrupt enable */ #define RTC_UIE 0x10 /* update-finished interrupt enable */ -extern void gen_rtc_interrupt(unsigned long); - /* some dummy definitions */ +#define RTC_BATT_BAD 0x100 /* battery bad */ #define RTC_SQWE 0x08 /* enable square-wave output */ #define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ #define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ #define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ -static inline void get_rtc_time(struct rtc_time *time) +static inline unsigned int get_rtc_time(struct rtc_time *time) { /* * Only the values that we read from the RTC are set. We leave @@ -39,6 +37,7 @@ static inline void get_rtc_time(struct rtc_time *time) * by the RTC when initially set to a non-zero value. */ mach_hwclk(0, time); + return RTC_24H; } static inline int set_rtc_time(struct rtc_time *time) @@ -52,7 +51,7 @@ static inline unsigned int get_rtc_ss(void) return mach_get_ss(); else{ struct rtc_time h; - + get_rtc_time(&h); return h.tm_sec; } @@ -72,7 +71,6 @@ static inline int set_rtc_pll(struct rtc_pll_info *pll) else return -EINVAL; } - #endif /* __KERNEL__ */ #endif /* _ASM__RTC_H */ diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 0711d71bc858..27c38b240736 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -63,7 +63,7 @@ struct rtc_pll_info { }; /* - * ioctl calls that are permitted to the /dev/rtc interface, if + * ioctl calls that are permitted to the /dev/rtc interface, if * any of the RTC drivers are enabled. */ @@ -87,6 +87,7 @@ struct rtc_pll_info { #define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/ #define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/ + #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ -- cgit v1.2.3 From 334e9d0003549315bac56f4be3d95a9143cf9fe9 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:04:45 -0800 Subject: [PATCH] M68k SCSI driver updates M68k SCSI drivers: update for the changes in 2.5.60: o Replace `->lun' by `->device->lun' o Replace `->target' by `->device->id' o Replace `->host' by `->device->host' --- drivers/scsi/53c7xx.c | 168 +++++++++++++++++++++---------------------- drivers/scsi/NCR53C9x.c | 18 ++--- drivers/scsi/a2091.c | 10 +-- drivers/scsi/atari_NCR5380.c | 116 +++++++++++++++--------------- drivers/scsi/atari_scsi.c | 2 +- drivers/scsi/gvp11.c | 59 +++++++-------- drivers/scsi/sun3_NCR5380.c | 108 ++++++++++++++-------------- 7 files changed, 241 insertions(+), 240 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/53c7xx.c b/drivers/scsi/53c7xx.c index 799dad164ba9..55d7c145d5b3 100644 --- a/drivers/scsi/53c7xx.c +++ b/drivers/scsi/53c7xx.c @@ -1759,7 +1759,7 @@ NCR53c7xx_run_tests (struct Scsi_Host *host) { static void NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) { Scsi_Cmnd *c = cmd->cmd; - struct Scsi_Host *host = c->host; + struct Scsi_Host *host = c->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; int i; @@ -1784,18 +1784,18 @@ NCR53c7xx_dsa_fixup (struct NCR53c7x0_cmd *cmd) { */ patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_lun, c->lun); + dsa_temp_lun, c->device->lun); patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), dsa_temp_addr_next, virt_to_bus(&cmd->dsa_next_addr)); patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), dsa_temp_next, virt_to_bus(cmd->dsa) + Ent_dsa_zero - Ent_dsa_code_template + A_dsa_next); patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->target].script)); + dsa_temp_sync, virt_to_bus((void *)hostdata->sync[c->device->id].script)); patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_sscf_710, virt_to_bus((void *)&hostdata->sync[c->target].sscf_710)); + dsa_sscf_710, virt_to_bus((void *)&hostdata->sync[c->device->id].sscf_710)); patch_abs_tci_data (cmd->dsa, Ent_dsa_code_template / sizeof(u32), - dsa_temp_target, 1 << c->target); + dsa_temp_target, 1 << c->device->id); /* XXX - new pointer stuff */ patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32), dsa_temp_addr_saved_pointer, virt_to_bus(&cmd->saved_data_pointer)); @@ -1856,7 +1856,7 @@ run_process_issue_queue(void) { static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) { Scsi_Cmnd *c = cmd->cmd; - struct Scsi_Host *host = c->host; + struct Scsi_Host *host = c->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; unsigned long flags; @@ -1940,7 +1940,7 @@ abnormal_finished (struct NCR53c7x0_cmd *cmd, int result) { host->host_no, c->pid); else if (linux_search) { *linux_prev = linux_search->next; - --hostdata->busy[c->target][c->lun]; + --hostdata->busy[c->device->id][c->device->lun]; } /* Return the NCR command structure to the free list */ @@ -2287,9 +2287,9 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct hostdata->dsp_changed = 1; if (cmd && (cmd->flags & CMD_FLAG_SDTR)) { printk ("scsi%d : target %d rejected SDTR\n", host->host_no, - c->target); + c->device->id); cmd->flags &= ~CMD_FLAG_SDTR; - asynchronous (host, c->target); + asynchronous (host, c->device->id); print = 0; } break; @@ -2311,7 +2311,7 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct if (print) { printk ("scsi%d : received message", host->host_no); if (c) - printk (" from target %d lun %d ", c->target, c->lun); + printk (" from target %d lun %d ", c->device->id, c->device->lun); print_msg ((unsigned char *) hostdata->msg_buf); printk("\n"); } @@ -2331,7 +2331,7 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct if (cmd) { char buf[80]; - sprintf (buf, "scsi%d : target %d %s ", host->host_no, c->target, + sprintf (buf, "scsi%d : target %d %s ", host->host_no, c->device->id, (cmd->flags & CMD_FLAG_SDTR) ? "accepting" : "requesting"); print_synchronous (buf, (unsigned char *) hostdata->msg_buf); @@ -2346,10 +2346,10 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct if (cmd->flags & CMD_FLAG_SDTR) { cmd->flags &= ~CMD_FLAG_SDTR; if (hostdata->msg_buf[4]) - synchronous (host, c->target, (unsigned char *) + synchronous (host, c->device->id, (unsigned char *) hostdata->msg_buf); else - asynchronous (host, c->target); + asynchronous (host, c->device->id); hostdata->dsp = hostdata->script + hostdata->E_accept_message / sizeof(u32); hostdata->dsp_changed = 1; @@ -2357,11 +2357,11 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct } else { if (hostdata->options & OPTION_SYNCHRONOUS) { cmd->flags |= CMD_FLAG_DID_SDTR; - synchronous (host, c->target, (unsigned char *) + synchronous (host, c->device->id, (unsigned char *) hostdata->msg_buf); } else { hostdata->msg_buf[4] = 0; /* 0 offset = async */ - asynchronous (host, c->target); + asynchronous (host, c->device->id); } patch_dsa_32 (cmd->dsa, dsa_msgout_other, 0, 5); patch_dsa_32 (cmd->dsa, dsa_msgout_other, 1, (u32) @@ -2545,9 +2545,9 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct host->host_no, NCR53c7x0_read8(SXFER_REG)); if (c) { print_insn (host, (u32 *) - hostdata->sync[c->target].script, "", 1); + hostdata->sync[c->device->id].script, "", 1); print_insn (host, (u32 *) - hostdata->sync[c->target].script + 2, "", 1); + hostdata->sync[c->device->id].script + 2, "", 1); } } return SPECIFIC_INT_RESTART; @@ -2658,7 +2658,7 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct if (hostdata->options & (OPTION_DEBUG_SCRIPT|OPTION_DEBUG_INTR)) { if (c) printk("scsi%d : target %d lun %d disconnecting\n", - host->host_no, c->target, c->lun); + host->host_no, c->device->id, c->device->lun); else printk("scsi%d : unknown target disconnecting\n", host->host_no); @@ -2680,9 +2680,9 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct #endif if (c) { print_insn (host, (u32 *) - hostdata->sync[c->target].script, "", 1); + hostdata->sync[c->device->id].script, "", 1); print_insn (host, (u32 *) - hostdata->sync[c->target].script + 2, "", 1); + hostdata->sync[c->device->id].script + 2, "", 1); } } return SPECIFIC_INT_RESTART; @@ -2734,8 +2734,8 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct if ((hostdata->chip / 100) == 8) { scntl3 = NCR53c7x0_read8 (SCNTL3_REG_800); if (c) { - if (sxfer != hostdata->sync[c->target].sxfer_sanity || - scntl3 != hostdata->sync[c->target].scntl3_sanity) { + if (sxfer != hostdata->sync[c->device->id].sxfer_sanity || + scntl3 != hostdata->sync[c->device->id].scntl3_sanity) { printk ("scsi%d : sync sanity check failed sxfer=0x%x, scntl3=0x%x", host->host_no, sxfer, scntl3); NCR53c7x0_write8 (SXFER_REG, sxfer); @@ -2746,12 +2746,12 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct host->host_no, (int) sxfer, (int) scntl3); } else { if (c) { - if (sxfer != hostdata->sync[c->target].sxfer_sanity) { + if (sxfer != hostdata->sync[c->device->id].sxfer_sanity) { printk ("scsi%d : sync sanity check failed sxfer=0x%x", host->host_no, sxfer); NCR53c7x0_write8 (SXFER_REG, sxfer); NCR53c7x0_write8 (SBCL_REG, - hostdata->sync[c->target].sscf_710); + hostdata->sync[c->device->id].sscf_710); } } else printk ("scsi%d : unknown command sxfer=0x%x\n", @@ -2807,9 +2807,9 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct (DCMD_REG)) == hostdata->script + Ent_select_check_dsa / sizeof(u32) ? "selection" : "reselection"; - if (c && sdid != c->target) { + if (c && sdid != c->device->id) { printk ("scsi%d : SDID target %d != DSA target %d at %s\n", - host->host_no, sdid, c->target, where); + host->host_no, sdid, c->device->id, where); print_lots(host); dump_events (host, 20); return SPECIFIC_INT_PANIC; @@ -2855,7 +2855,7 @@ NCR53c7x0_dstat_sir_intr (struct Scsi_Host *host, struct if (event->event == EVENT_RESELECT) event->lun = hostdata->reselected_identify & 0xf; else if (c) - event->lun = c->lun; + event->lun = c->device->lun; else event->lun = 255; do_gettimeofday(&(event->time)); @@ -3049,7 +3049,7 @@ my_free_page (void *addr, int dummy) static struct NCR53c7x0_cmd * allocate_cmd (Scsi_Cmnd *cmd) { - struct Scsi_Host *host = cmd->host; + struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; u32 real; /* Real address */ @@ -3061,8 +3061,8 @@ allocate_cmd (Scsi_Cmnd *cmd) { printk ("scsi%d : num_cmds = %d, can_queue = %d\n" " target = %d, lun = %d, %s\n", host->host_no, hostdata->num_cmds, host->can_queue, - cmd->target, cmd->lun, (hostdata->cmd_allocated[cmd->target] & - (1 << cmd->lun)) ? "already allocated" : "not allocated"); + cmd->device->id, cmd->device->lun, (hostdata->cmd_allocated[cmd->device->id] & + (1 << cmd->device->lun)) ? "already allocated" : "not allocated"); /* * If we have not yet reserved commands for this I_T_L nexus, and @@ -3070,11 +3070,11 @@ allocate_cmd (Scsi_Cmnd *cmd) { * being allocated under 1.3.x, or being outside of scan_scsis in * 1.2.x), do so now. */ - if (!(hostdata->cmd_allocated[cmd->target] & (1 << cmd->lun)) && + if (!(hostdata->cmd_allocated[cmd->device->id] & (1 << cmd->device->lun)) && cmd->device && cmd->device->has_cmdblocks) { if ((hostdata->extra_allocate + hostdata->num_cmds) < host->can_queue) hostdata->extra_allocate += host->cmd_per_lun; - hostdata->cmd_allocated[cmd->target] |= (1 << cmd->lun); + hostdata->cmd_allocated[cmd->device->id] |= (1 << cmd->device->lun); } for (; hostdata->extra_allocate > 0 ; --hostdata->extra_allocate, @@ -3130,7 +3130,7 @@ allocate_cmd (Scsi_Cmnd *cmd) { local_irq_restore(flags); if (!tmp) printk ("scsi%d : can't allocate command for target %d lun %d\n", - host->host_no, cmd->target, cmd->lun); + host->host_no, cmd->device->id, cmd->device->lun); return tmp; } @@ -3150,7 +3150,7 @@ allocate_cmd (Scsi_Cmnd *cmd) { static struct NCR53c7x0_cmd * create_cmd (Scsi_Cmnd *cmd) { NCR53c7x0_local_declare(); - struct Scsi_Host *host = cmd->host; + struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; struct NCR53c7x0_cmd *tmp; /* NCR53c7x0_cmd structure for this command */ @@ -3166,7 +3166,7 @@ create_cmd (Scsi_Cmnd *cmd) { #endif unsigned long flags; u32 exp_select_indirect; /* Used in sanity check */ - NCR53c7x0_local_setup(cmd->host); + NCR53c7x0_local_setup(cmd->device->host); if (!(tmp = allocate_cmd (cmd))) return NULL; @@ -3322,45 +3322,45 @@ create_cmd (Scsi_Cmnd *cmd) { if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) { - exp_select_indirect = ((1 << cmd->target) << 16) | - (hostdata->sync[cmd->target].sxfer_sanity << 8); + exp_select_indirect = ((1 << cmd->device->id) << 16) | + (hostdata->sync[cmd->device->id].sxfer_sanity << 8); - if (hostdata->sync[cmd->target].select_indirect != + if (hostdata->sync[cmd->device->id].select_indirect != exp_select_indirect) { printk ("scsi%d : sanity check failed select_indirect=0x%x\n", - host->host_no, hostdata->sync[cmd->target].select_indirect); + host->host_no, hostdata->sync[cmd->device->id].select_indirect); FATAL(host); } } patch_dsa_32(tmp->dsa, dsa_select, 0, - hostdata->sync[cmd->target].select_indirect); + hostdata->sync[cmd->device->id].select_indirect); /* * Right now, we'll do the WIDE and SYNCHRONOUS negotiations on * different commands; although it should be trivial to do them * both at the same time. */ - if (hostdata->initiate_wdtr & (1 << cmd->target)) { + if (hostdata->initiate_wdtr & (1 << cmd->device->id)) { memcpy ((void *) (tmp->select + 1), (void *) wdtr_message, sizeof(wdtr_message)); patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(wdtr_message)); local_irq_save(flags); - hostdata->initiate_wdtr &= ~(1 << cmd->target); + hostdata->initiate_wdtr &= ~(1 << cmd->device->id); local_irq_restore(flags); - } else if (hostdata->initiate_sdtr & (1 << cmd->target)) { + } else if (hostdata->initiate_sdtr & (1 << cmd->device->id)) { memcpy ((void *) (tmp->select + 1), (void *) sdtr_message, sizeof(sdtr_message)); patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1 + sizeof(sdtr_message)); tmp->flags |= CMD_FLAG_SDTR; local_irq_save(flags); - hostdata->initiate_sdtr &= ~(1 << cmd->target); + hostdata->initiate_sdtr &= ~(1 << cmd->device->id); local_irq_restore(flags); } #if 1 - else if (!(hostdata->talked_to & (1 << cmd->target)) && + else if (!(hostdata->talked_to & (1 << cmd->device->id)) && !(hostdata->options & OPTION_NO_ASYNC)) { memcpy ((void *) (tmp->select + 1), (void *) async_message, @@ -3372,9 +3372,9 @@ create_cmd (Scsi_Cmnd *cmd) { else patch_dsa_32(tmp->dsa, dsa_msgout, 0, 1); - hostdata->talked_to |= (1 << cmd->target); + hostdata->talked_to |= (1 << cmd->device->id); tmp->select[0] = (hostdata->options & OPTION_DISCONNECT) ? - IDENTIFY (1, cmd->lun) : IDENTIFY (0, cmd->lun); + IDENTIFY (1, cmd->device->lun) : IDENTIFY (0, cmd->device->lun); patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select)); patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len); patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(tmp->cmnd)); @@ -3591,7 +3591,7 @@ create_cmd (Scsi_Cmnd *cmd) { int NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { - struct Scsi_Host *host = cmd->host; + struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; unsigned long flags; @@ -3604,9 +3604,9 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { #ifdef VALID_IDS /* Ignore commands on invalid IDs */ - if (!hostdata->valid_ids[cmd->target]) { + if (!hostdata->valid_ids[cmd->device->id]) { printk("scsi%d : ignoring target %d lun %d\n", host->host_no, - cmd->target, cmd->lun); + cmd->device->id, cmd->device->lun); cmd->result = (DID_BAD_TARGET << 16); done(cmd); return 0; @@ -3616,16 +3616,16 @@ NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { local_irq_save(flags); if ((hostdata->options & (OPTION_DEBUG_INIT_ONLY|OPTION_DEBUG_PROBE_ONLY)) || ((hostdata->options & OPTION_DEBUG_TARGET_LIMIT) && - !(hostdata->debug_lun_limit[cmd->target] & (1 << cmd->lun))) + !(hostdata->debug_lun_limit[cmd->device->id] & (1 << cmd->device->lun))) #ifdef LINUX_1_2 - || cmd->target > 7 + || cmd->device->id > 7 #else - || cmd->target > host->max_id + || cmd->device->id > host->max_id #endif - || cmd->target == host->this_id + || cmd->device->id == host->this_id || hostdata->state == STATE_DISABLED) { printk("scsi%d : disabled or bad target %d lun %d\n", host->host_no, - cmd->target, cmd->lun); + cmd->device->id, cmd->device->lun); cmd->result = (DID_BAD_TARGET << 16); done(cmd); local_irq_restore(flags); @@ -3738,7 +3738,7 @@ to_schedule_list (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, --i, ncrcurrent += 2 /* JUMP instructions are two words */); if (i > 0) { - ++hostdata->busy[tmp->target][tmp->lun]; + ++hostdata->busy[tmp->device->id][tmp->device->lun]; cmd->next = hostdata->running_list; hostdata->running_list = cmd; @@ -3799,7 +3799,7 @@ busyp (struct Scsi_Host *host, struct NCR53c7x0_hostdata *hostdata, /* FIXME : in the future, this needs to accommodate SCSI-II tagged queuing, and we may be able to play with fairness here a bit. */ - return hostdata->busy[cmd->target][cmd->lun]; + return hostdata->busy[cmd->device->id][cmd->device->lun]; } /* @@ -3873,7 +3873,7 @@ process_issue_queue (unsigned long flags) { if (tmp->host_scribble) { if (hostdata->options & OPTION_DEBUG_QUEUES) printk ("scsi%d : moving command for target %d lun %d to start list\n", - host->host_no, tmp->target, tmp->lun); + host->host_no, tmp->device->id, tmp->device->lun); to_schedule_list (host, hostdata, @@ -3937,7 +3937,7 @@ intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { printk ("scsi%d : Selection Timeout\n", host->host_no); if (cmd) { printk("scsi%d : target %d, lun %d, command ", - host->host_no, cmd->cmd->target, cmd->cmd->lun); + host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun); print_command (cmd->cmd->cmnd); printk("scsi%d : dsp = 0x%x (virt 0x%p)\n", host->host_no, NCR53c7x0_read32(DSP_REG), @@ -3975,7 +3975,7 @@ intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { fatal = 1; if (cmd) { printk("scsi%d : target %d lun %d unexpected disconnect\n", - host->host_no, cmd->cmd->target, cmd->cmd->lun); + host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun); print_lots (host); abnormal_finished(cmd, DID_ERROR << 16); } else @@ -3991,7 +3991,7 @@ intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { fatal = 1; if (cmd && cmd->cmd) { printk("scsi%d : target %d lun %d parity error.\n", - host->host_no, cmd->cmd->target, cmd->cmd->lun); + host->host_no, cmd->cmd->device->id, cmd->cmd->device->lun); abnormal_finished (cmd, DID_PARITY << 16); } else printk("scsi%d : parity error\n", host->host_no); @@ -4199,7 +4199,7 @@ restart: if (cmd_prev_ptr) *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next; - --hostdata->busy[tmp->target][tmp->lun]; + --hostdata->busy[tmp->device->id][tmp->device->lun]; cmd->next = hostdata->free; hostdata->free = cmd; @@ -4207,7 +4207,7 @@ restart: if (hostdata->options & OPTION_DEBUG_INTR) { printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", - host->host_no, tmp->pid, tmp->target, tmp->lun, tmp->result); + host->host_no, tmp->pid, tmp->device->id, tmp->device->lun, tmp->result); print_command (tmp->cmnd); } @@ -4292,8 +4292,8 @@ NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) { if (hostdata->options & OPTION_DEBUG_INTR) { if (cmd) { printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", - host->host_no, cmd->cmd->pid, (int) cmd->cmd->target, - (int) cmd->cmd->lun); + host->host_no, cmd->cmd->pid, (int) cmd->cmd->device->id, + (int) cmd->cmd->device->lun); print_command (cmd->cmd->cmnd); } else { printk("scsi%d : no active command\n", host->host_no); @@ -4671,7 +4671,7 @@ intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) { hostdata->dsp = dsp + 2 /* two _words_ */; hostdata->dsp_changed = 1; printk ("scsi%d : target %d ignored SDTR and went into COMMAND OUT\n", - host->host_no, cmd->cmd->target); + host->host_no, cmd->cmd->device->id); cmd->flags &= ~CMD_FLAG_SDTR; action = ACTION_CONTINUE; break; @@ -5136,7 +5136,7 @@ print_insn (struct Scsi_Host *host, const u32 *insn, int NCR53c7xx_abort (Scsi_Cmnd *cmd) { NCR53c7x0_local_declare(); - struct Scsi_Host *host = cmd->host; + struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) host->hostdata[0] : NULL; unsigned long flags; @@ -5242,7 +5242,7 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) { return SCSI_ABORT_NOT_RUNNING; } else { printk ("scsi%d : DANGER : command running, can not abort.\n", - cmd->host->host_no); + cmd->device->host->host_no); local_irq_restore(flags); return SCSI_ABORT_BUSY; } @@ -5273,7 +5273,7 @@ NCR53c7xx_abort (Scsi_Cmnd *cmd) { * command was ever counted as BUSY, so if we end up here we can * decrement the busy count if and only if it is necessary. */ - --hostdata->busy[cmd->target][cmd->lun]; + --hostdata->busy[cmd->device->id][cmd->device->lun]; } local_irq_restore(flags); cmd->scsi_done(cmd); @@ -5318,7 +5318,7 @@ NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) { * each command. */ Scsi_Cmnd *nuke_list = NULL; - struct Scsi_Host *host = cmd->host; + struct Scsi_Host *host = cmd->device->host; struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0]; @@ -5388,7 +5388,7 @@ NCR53c7xx_reset (Scsi_Cmnd *cmd, unsigned int reset_flags) { static int insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) { struct NCR53c7x0_hostdata *hostdata = - (struct NCR53c7x0_hostdata *) cmd->host->hostdata[0]; + (struct NCR53c7x0_hostdata *) cmd->device->host->hostdata[0]; struct NCR53c7x0_cmd *ncmd = (struct NCR53c7x0_cmd *) cmd->host_scribble; int offset = 0, buffers; @@ -5418,7 +5418,7 @@ insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) { --buffers, offset += segment->length, ++segment) #if 0 printk("scsi%d: comparing 0x%p to 0x%p\n", - cmd->host->host_no, saved, page_address(segment->page+segment->offset); + cmd->device->host->host_no, saved, page_address(segment->page+segment->offset); #else ; #endif @@ -5456,7 +5456,7 @@ print_progress (Scsi_Cmnd *cmd) { int offset, i; char *where; u32 *ptr; - NCR53c7x0_local_setup (cmd->host); + NCR53c7x0_local_setup (cmd->device->host); if (check_address ((unsigned long) ncmd,sizeof (struct NCR53c7x0_cmd)) == 0) { @@ -5484,15 +5484,15 @@ print_progress (Scsi_Cmnd *cmd) { if (offset != -1) printk ("scsi%d : %s data pointer at offset %d\n", - cmd->host->host_no, where, offset); + cmd->device->host->host_no, where, offset); else { int size; printk ("scsi%d : can't determine %s data pointer offset\n", - cmd->host->host_no, where); + cmd->device->host->host_no, where); if (ncmd) { - size = print_insn (cmd->host, + size = print_insn (cmd->device->host, bus_to_virt(ncmd->saved_data_pointer), "", 1); - print_insn (cmd->host, + print_insn (cmd->device->host, bus_to_virt(ncmd->saved_data_pointer) + size * sizeof(u32), "", 1); } @@ -5549,7 +5549,7 @@ print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) { /* XXX Maybe we should access cmd->host_scribble->result here. RGH */ if (cmd) { printk(" result = 0x%x, target = %d, lun = %d, cmd = ", - cmd->result, cmd->target, cmd->lun); + cmd->result, cmd->device->id, cmd->device->lun); print_command(cmd->cmnd); } else printk("\n"); @@ -5558,11 +5558,11 @@ print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) { if (cmd) { printk("scsi%d target %d : sxfer_sanity = 0x%x, scntl3_sanity = 0x%x\n" " script : ", - host->host_no, cmd->target, - hostdata->sync[cmd->target].sxfer_sanity, - hostdata->sync[cmd->target].scntl3_sanity); - for (i = 0; i < (sizeof(hostdata->sync[cmd->target].script) / 4); ++i) - printk ("0x%x ", hostdata->sync[cmd->target].script[i]); + host->host_no, cmd->device->id, + hostdata->sync[cmd->device->id].sxfer_sanity, + hostdata->sync[cmd->device->id].scntl3_sanity); + for (i = 0; i < (sizeof(hostdata->sync[cmd->device->id].script) / 4); ++i) + printk ("0x%x ", hostdata->sync[cmd->device->id].script[i]); printk ("\n"); print_progress (cmd); } @@ -5604,7 +5604,7 @@ print_queues (struct Scsi_Host *host) { -> dsa, ""); } else printk ("scsi%d : scsi pid %ld for target %d lun %d has no NCR53c7x0_cmd\n", - host->host_no, cmd->pid, cmd->target, cmd->lun); + host->host_no, cmd->pid, cmd->device->id, cmd->device->lun); local_irq_restore(flags); } diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index a1f8470c1a5f..340614409b3b 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -1099,7 +1099,7 @@ do_sync_known: * disconnect. */ ESPMISC(("esp: Selecting device for first time. target=%d " - "lun=%d\n", target, SCptr->lun)); + "lun=%d\n", target, SCptr->device->lun)); if(!SDptr->borken && !esp_dev->disconnect) esp_dev->disconnect = 1; @@ -1173,7 +1173,7 @@ do_sync_known: if(((SDptr->scsi_level < 3) && (SDptr->type != TYPE_TAPE)) || toshiba_cdrom_hwbug_wkaround || SDptr->borken) { ESPMISC((KERN_INFO "esp%d: Disabling DISCONNECT for target %d " - "lun %d\n", esp->esp_id, SCptr->target, SCptr->lun)); + "lun %d\n", esp->esp_id, SCptr->device->id, SCptr->device->lun)); esp_dev->disconnect = 0; *cmdp++ = IDENTIFY(0, lun); } else { @@ -1255,8 +1255,8 @@ int esp_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) esp->dma_led_on(esp); /* We use the scratch area. */ - ESPQUEUE(("esp_queue: target=%d lun=%d ", SCpnt->target, SCpnt->lun)); - ESPDISC(("N<%02x,%02x>", SCpnt->target, SCpnt->lun)); + ESPQUEUE(("esp_queue: target=%d lun=%d ", SCpnt->device->id, SCpnt->lun)); + ESPDISC(("N<%02x,%02x>", SCpnt->device->id, SCpnt->lun)); esp_get_dmabufs(esp, SCpnt); esp_save_pointers(esp, SCpnt); /* FIXME for tag queueing */ @@ -2235,7 +2235,7 @@ static int esp_do_freebus(struct NCR_ESP *esp, struct ESP_regs *eregs) * state. */ ESPMISC(("esp: Status <%d> for target %d lun %d\n", - SCptr->SCp.Status, SCptr->target, SCptr->lun)); + SCptr->SCp.Status, SCptr->device->id, SCptr->device->lun)); /* But don't do this when spinning up a disk at * boot time while we poll for completion as it @@ -2246,14 +2246,14 @@ static int esp_do_freebus(struct NCR_ESP *esp, struct ESP_regs *eregs) if(esp_should_clear_sync(SCptr) != 0) esp_dev->sync = 0; } - ESPDISC(("F<%02x,%02x>", SCptr->target, SCptr->lun)); + ESPDISC(("F<%02x,%02x>", SCptr->device->id, SCptr->device->lun)); esp_done(esp, ((SCptr->SCp.Status & 0xff) | ((SCptr->SCp.Message & 0xff)<<8) | (DID_OK << 16))); } else if(esp->prevmsgin == DISCONNECT) { /* Normal disconnect. */ esp_cmd(esp, eregs, ESP_CMD_ESEL); - ESPDISC(("D<%02x,%02x>", SCptr->target, SCptr->lun)); + ESPDISC(("D<%02x,%02x>", SCptr->device->id, SCptr->device->lun)); append_SC(&esp->disconnected_SC, SCptr); esp->current_SC = NULL; if(esp->issue_SC) @@ -2811,7 +2811,7 @@ static int esp_select_complete(struct NCR_ESP *esp, struct ESP_regs *eregs) /* Else, there really isn't anyone there. */ ESPMISC(("esp: selection failure, maybe nobody there?\n")); ESPMISC(("esp: target %d lun %d\n", - SCptr->target, SCptr->lun)); + SCptr->device->id, SCptr->device->lun)); esp_done(esp, (DID_BAD_TARGET << 16)); } return do_intr_end; @@ -3084,7 +3084,7 @@ static int check_multibyte_msg(struct NCR_ESP *esp, ESPSDTR(("soff=%2x stp=%2x cfg3=%2x\n", esp_dev->sync_max_offset, esp_dev->sync_min_period, - esp->config3[SCptr->target])); + esp->config3[SCptr->device->id])); esp->snip = 0; } else if(esp_dev->sync_max_offset) { diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index f8b04da74c83..bf82d0b2df1b 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -52,7 +52,7 @@ static int dma_setup (Scsi_Cmnd *cmd, int dir_in) { unsigned short cntr = CNTR_PDMD | CNTR_INTEN; unsigned long addr = virt_to_bus(cmd->SCp.ptr); - struct Scsi_Host *instance = cmd->host; + struct Scsi_Host *instance = cmd->device->host; /* don't allow DMA if the physical address is bad */ if (addr & A2091_XFER_MASK || @@ -102,12 +102,12 @@ static int dma_setup (Scsi_Cmnd *cmd, int dir_in) cntr |= CNTR_DDIR; /* remember direction */ - HDATA(cmd->host)->dma_dir = dir_in; + HDATA(cmd->device->host)->dma_dir = dir_in; - DMA(cmd->host)->CNTR = cntr; + DMA(cmd->device->host)->CNTR = cntr; /* setup DMA *physical* address */ - DMA(cmd->host)->ACR = addr; + DMA(cmd->device->host)->ACR = addr; if (dir_in){ /* invalidate any cache */ @@ -117,7 +117,7 @@ static int dma_setup (Scsi_Cmnd *cmd, int dir_in) cache_push (addr, cmd->SCp.this_residual); } /* start DMA */ - DMA(cmd->host)->ST_DMA = 1; + DMA(cmd->device->host)->ST_DMA = 1; /* return success */ return 0; diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index a5ce400cd2d9..387a14db1fa9 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -266,7 +266,7 @@ static Scsi_Host_Template *the_template = NULL; #define NEXTADDR(cmd) ((Scsi_Cmnd **)&((cmd)->host_scribble)) #define HOSTNO instance->host_no -#define H_NO(cmd) (cmd)->host->host_no +#define H_NO(cmd) (cmd)->device->host->host_no #ifdef SUPPORT_TAGS @@ -350,17 +350,17 @@ static void __init init_tags( void ) static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged ) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); - if (hostdata->busy[cmd->target] & (1 << cmd->lun)) + if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)) return( 1 ); if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) return( 0 ); - if (TagAlloc[cmd->target][cmd->lun].nr_allocated >= - TagAlloc[cmd->target][cmd->lun].queue_size ) { + if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >= + TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) { TAG_PRINTK( "scsi%d: target %d lun %d: no free tags\n", - H_NO(cmd), cmd->target, cmd->lun ); + H_NO(cmd), cmd->device->id, cmd->device->lun ); return( 1 ); } return( 0 ); @@ -374,7 +374,7 @@ static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged ) static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); /* If we or the target don't support tagged queuing, allocate the LUN for * an untagged command. @@ -382,19 +382,19 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) { cmd->tag = TAG_NONE; - hostdata->busy[cmd->target] |= (1 << cmd->lun); + hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); TAG_PRINTK( "scsi%d: target %d lun %d now allocated by untagged " - "command\n", H_NO(cmd), cmd->target, cmd->lun ); + "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun ); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; cmd->tag = find_first_zero_bit( ta->allocated, MAX_TAGS ); set_bit( cmd->tag, ta->allocated ); ta->nr_allocated++; TAG_PRINTK( "scsi%d: using tag %d for target %d lun %d " "(now %d tags in use)\n", - H_NO(cmd), cmd->tag, cmd->target, cmd->lun, + H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun, ta->nr_allocated ); } } @@ -406,23 +406,23 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) static void cmd_free_tag( Scsi_Cmnd *cmd ) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); if (cmd->tag == TAG_NONE) { - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); TAG_PRINTK( "scsi%d: target %d lun %d untagged cmd finished\n", - H_NO(cmd), cmd->target, cmd->lun ); + H_NO(cmd), cmd->device->id, cmd->device->lun ); } else if (cmd->tag >= MAX_TAGS) { printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", H_NO(cmd), cmd->tag ); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; clear_bit( cmd->tag, ta->allocated ); ta->nr_allocated--; TAG_PRINTK( "scsi%d: freed tag %d for target %d lun %d\n", - H_NO(cmd), cmd->tag, cmd->target, cmd->lun ); + H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun ); } } @@ -811,7 +811,7 @@ lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) int i, s; unsigned char *command; SPRINTF("scsi%d: destination target %d, lun %d\n", - H_NO(cmd), cmd->target, cmd->lun); + H_NO(cmd), cmd->device->id, cmd->device->lun); SPRINTF(" command = "); command = cmd->cmnd; SPRINTF("%2d (0x%02x)", command[0], command[0]); @@ -903,7 +903,7 @@ static int NCR5380_init (struct Scsi_Host *instance, int flags) static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); Scsi_Cmnd *tmp; int oldto; unsigned long flags; @@ -937,15 +937,15 @@ int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) case WRITE: case WRITE_6: case WRITE_10: - hostdata->time_write[cmd->target] -= (jiffies - hostdata->timebase); - hostdata->bytes_write[cmd->target] += cmd->request_bufflen; + hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase); + hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen; hostdata->pendingw++; break; case READ: case READ_6: case READ_10: - hostdata->time_read[cmd->target] -= (jiffies - hostdata->timebase); - hostdata->bytes_read[cmd->target] += cmd->request_bufflen; + hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase); + hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen; hostdata->pendingr++; break; } @@ -1086,8 +1086,8 @@ static void NCR5380_main (void *bl) #if (NDEBUG & NDEBUG_LISTS) if (prev != tmp) printk("MAIN tmp=%p target=%d busy=%d lun=%d\n", - tmp, tmp->target, hostdata->busy[tmp->target], - tmp->lun); + tmp, tmp->device->id, hostdata->busy[tmp->device->id], + tmp->device->lun); #endif /* When we find one, remove it from the issue queue. */ /* ++guenther: possible race with Falcon locking */ @@ -1095,7 +1095,7 @@ static void NCR5380_main (void *bl) #ifdef SUPPORT_TAGS !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE) #else - !(hostdata->busy[tmp->target] & (1 << tmp->lun)) + !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun)) #endif ) { /* ++guenther: just to be sure, this must be atomic */ @@ -1121,7 +1121,7 @@ static void NCR5380_main (void *bl) */ MAIN_PRINTK("scsi%d: main(): command for target %d " "lun %d removed from issue_queue\n", - HOSTNO, tmp->target, tmp->lun); + HOSTNO, tmp->device->id, tmp->device->lun); /* * REQUEST SENSE commands are issued without tagged * queueing, even on SCSI-II devices because the @@ -1355,15 +1355,15 @@ static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd) case WRITE: case WRITE_6: case WRITE_10: - hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase); - /*hostdata->bytes_write[cmd->target] += cmd->request_bufflen;*/ + hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase); + /*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/ hostdata->pendingw--; break; case READ: case READ_6: case READ_10: - hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase); - /*hostdata->bytes_read[cmd->target] += cmd->request_bufflen;*/ + hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase); + /*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/ hostdata->pendingr--; break; } @@ -1524,7 +1524,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) * the host and target ID's on the SCSI bus. */ - NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->target))); + NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id))); /* * Raise ATN while SEL is true before BSY goes false from arbitration, @@ -1577,7 +1577,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) udelay(1); - SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->target); + SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id); /* * The SCSI specification calls for a 250 ms timeout for the actual @@ -1628,7 +1628,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - if (hostdata->targets_present & (1 << cmd->target)) { + if (hostdata->targets_present & (1 << cmd->device->id)) { printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO); if (hostdata->restart_select) printk(KERN_NOTICE "\trestart select\n"); @@ -1650,7 +1650,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) return 0; } - hostdata->targets_present |= (1 << cmd->target); + hostdata->targets_present |= (1 << cmd->device->id); /* * Since we followed the SCSI spec, and raised ATN while SEL @@ -1671,8 +1671,8 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) while (!(NCR5380_read(STATUS_REG) & SR_REQ)); SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n", - HOSTNO, cmd->target); - tmp[0] = IDENTIFY(1, cmd->lun); + HOSTNO, cmd->device->id); + tmp[0] = IDENTIFY(1, cmd->device->lun); #ifdef SUPPORT_TAGS if (cmd->tag != TAG_NONE) { @@ -1694,7 +1694,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) /* XXX need to handle errors here */ hostdata->connected = cmd; #ifndef SUPPORT_TAGS - hostdata->busy[cmd->target] |= (1 << cmd->lun); + hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); #endif initialize_SCp(cmd); @@ -2084,7 +2084,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) * polled-IO. */ printk(KERN_NOTICE "scsi%d: switching target %d " "lun %d to slow handshake\n", HOSTNO, - cmd->target, cmd->lun); + cmd->device->id, cmd->device->lun); cmd->device->borken = 1; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); @@ -2136,7 +2136,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); LNK_PRINTK("scsi%d: target %d lun %d linked command " - "complete.\n", HOSTNO, cmd->target, cmd->lun); + "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun); /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); @@ -2149,7 +2149,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) if (!cmd->next_link) { printk(KERN_NOTICE "scsi%d: target %d lun %d " "linked command complete, no next_link\n", - HOSTNO, cmd->target, cmd->lun); + HOSTNO, cmd->device->id, cmd->device->lun); sink = 1; do_abort (instance); return; @@ -2162,7 +2162,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); LNK_PRINTK("scsi%d: target %d lun %d linked request " "done, calling scsi_done().\n", - HOSTNO, cmd->target, cmd->lun); + HOSTNO, cmd->device->id, cmd->device->lun); #ifdef NCR5380_STATS collect_stats(hostdata, cmd); #endif @@ -2178,7 +2178,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) falcon_dont_release++; hostdata->connected = NULL; QU_PRINTK("scsi%d: command for target %d, lun %d " - "completed\n", HOSTNO, cmd->target, cmd->lun); + "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef SUPPORT_TAGS cmd_free_tag( cmd ); if (status_byte(cmd->SCp.Status) == QUEUE_FULL) { @@ -2190,16 +2190,16 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) */ /* ++Andreas: the mid level code knows about QUEUE_FULL now. */ - TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; TAG_PRINTK("scsi%d: target %d lun %d returned " "QUEUE_FULL after %d commands\n", - HOSTNO, cmd->target, cmd->lun, + HOSTNO, cmd->device->id, cmd->device->lun, ta->nr_allocated); if (ta->queue_size > ta->nr_allocated) ta->nr_allocated = ta->queue_size; } #else - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); @@ -2295,12 +2295,12 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) * the command is treated as untagged further on. */ cmd->device->tagged_supported = 0; - hostdata->busy[cmd->target] |= (1 << cmd->lun); + hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); cmd->tag = TAG_NONE; TAG_PRINTK("scsi%d: target %d lun %d rejected " "QUEUE_TAG message; tagged queuing " "disabled\n", - HOSTNO, cmd->target, cmd->lun); + HOSTNO, cmd->device->id, cmd->device->lun); break; } break; @@ -2317,7 +2317,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) QU_PRINTK("scsi%d: command for target %d lun %d was " "moved from connected to the " "disconnected_queue\n", HOSTNO, - cmd->target, cmd->lun); + cmd->device->id, cmd->device->lun); /* * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. @@ -2416,13 +2416,13 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) } else if (tmp != EXTENDED_MESSAGE) printk(KERN_DEBUG "scsi%d: rejecting unknown " "message %02x from target %d, lun %d\n", - HOSTNO, tmp, cmd->target, cmd->lun); + HOSTNO, tmp, cmd->device->id, cmd->device->lun); else printk(KERN_DEBUG "scsi%d: rejecting unknown " "extended message " "code %02x, length %d from target %d, lun %d\n", HOSTNO, extended_msg[1], extended_msg[0], - cmd->target, cmd->lun); + cmd->device->id, cmd->device->lun); msgout = MESSAGE_REJECT; @@ -2440,7 +2440,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) #ifdef SUPPORT_TAGS cmd_free_tag( cmd ); #else - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif hostdata->connected = NULL; cmd->result = DID_ERROR << 16; @@ -2576,7 +2576,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) { - if ((target_mask == (1 << tmp->target)) && (lun == tmp->lun) + if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun) #ifdef SUPPORT_TAGS && (tag == tmp->tag) #endif @@ -2619,7 +2619,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) hostdata->connected = tmp; RSL_PRINTK("scsi%d: nexus established, target = %d, lun = %d, tag = %d\n", - HOSTNO, tmp->target, tmp->lun, tmp->tag); + HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag); falcon_dont_release--; } @@ -2644,7 +2644,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) static int NCR5380_abort (Scsi_Cmnd *cmd) { - struct Scsi_Host *instance = cmd->host; + struct Scsi_Host *instance = cmd->device->host; SETUP_HOSTDATA(instance); Scsi_Cmnd *tmp, **prev; unsigned long flags; @@ -2698,7 +2698,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd) #ifdef SUPPORT_TAGS cmd_free_tag( cmd ); #else - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif local_irq_restore(flags); cmd->scsi_done(cmd); @@ -2805,7 +2805,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd) #ifdef SUPPORT_TAGS cmd_free_tag( tmp ); #else - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif local_irq_restore(flags); tmp->scsi_done(tmp); @@ -2849,7 +2849,7 @@ int NCR5380_abort (Scsi_Cmnd *cmd) static int NCR5380_bus_reset( Scsi_Cmnd *cmd) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); int i; unsigned long flags; #if 1 @@ -2860,7 +2860,7 @@ static int NCR5380_bus_reset( Scsi_Cmnd *cmd) printk(KERN_ERR "scsi%d: !!BINGO!! Falcon has no lock in NCR5380_reset\n", H_NO(cmd) ); - NCR5380_print_status (cmd->host); + NCR5380_print_status (cmd->device->host); /* get in phase */ NCR5380_write( TARGET_COMMAND_REG, diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c index 25412b60a3e7..17dfa0835bfb 100644 --- a/drivers/scsi/atari_scsi.c +++ b/drivers/scsi/atari_scsi.c @@ -823,7 +823,7 @@ int atari_scsi_bus_reset(Scsi_Cmnd *cmd) { int rv; struct NCR5380_hostdata *hostdata = - (struct NCR5380_hostdata *)cmd->host->hostdata; + (struct NCR5380_hostdata *)cmd->device->host->hostdata; /* For doing the reset, SCSI interrupts must be disabled first, * since the 5380 raises its IRQ line while _RST is active and we diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index ad2d6c301d30..f3ec633166a6 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -62,61 +62,62 @@ static int dma_setup (Scsi_Cmnd *cmd, int dir_in) static int scsi_alloc_out_of_range = 0; /* use bounce buffer if the physical address is bad */ - if (addr & HDATA(cmd->host)->dma_xfer_mask || + if (addr & HDATA(cmd->device->host)->dma_xfer_mask || (!dir_in && mm_end_of_chunk (addr, cmd->SCp.this_residual))) { - HDATA(cmd->host)->dma_bounce_len = (cmd->SCp.this_residual + 511) + HDATA(cmd->device->host)->dma_bounce_len = (cmd->SCp.this_residual + 511) & ~0x1ff; if( !scsi_alloc_out_of_range ) { - HDATA(cmd->host)->dma_bounce_buffer = - kmalloc (HDATA(cmd->host)->dma_bounce_len, GFP_KERNEL); - HDATA(cmd->host)->dma_buffer_pool = BUF_SCSI_ALLOCED; + HDATA(cmd->device->host)->dma_bounce_buffer = + kmalloc (HDATA(cmd->device->host)->dma_bounce_len, GFP_KERNEL); + HDATA(cmd->device->host)->dma_buffer_pool = BUF_SCSI_ALLOCED; } - if ( scsi_alloc_out_of_range || !HDATA(cmd->host)->dma_bounce_buffer) { - HDATA(cmd->host)->dma_bounce_buffer = - amiga_chip_alloc(HDATA(cmd->host)->dma_bounce_len, + if (scsi_alloc_out_of_range || + !HDATA(cmd->device->host)->dma_bounce_buffer) { + HDATA(cmd->device->host)->dma_bounce_buffer = + amiga_chip_alloc(HDATA(cmd->device->host)->dma_bounce_len, "GVP II SCSI Bounce Buffer"); - if(!HDATA(cmd->host)->dma_bounce_buffer) + if(!HDATA(cmd->device->host)->dma_bounce_buffer) { - HDATA(cmd->host)->dma_bounce_len = 0; + HDATA(cmd->device->host)->dma_bounce_len = 0; return 1; } - HDATA(cmd->host)->dma_buffer_pool = BUF_CHIP_ALLOCED; + HDATA(cmd->device->host)->dma_buffer_pool = BUF_CHIP_ALLOCED; } /* check if the address of the bounce buffer is OK */ - addr = virt_to_bus(HDATA(cmd->host)->dma_bounce_buffer); + addr = virt_to_bus(HDATA(cmd->device->host)->dma_bounce_buffer); - if (addr & HDATA(cmd->host)->dma_xfer_mask) { + if (addr & HDATA(cmd->device->host)->dma_xfer_mask) { /* fall back to Chip RAM if address out of range */ - if( HDATA(cmd->host)->dma_buffer_pool == BUF_SCSI_ALLOCED) { - kfree (HDATA(cmd->host)->dma_bounce_buffer); + if( HDATA(cmd->device->host)->dma_buffer_pool == BUF_SCSI_ALLOCED) { + kfree (HDATA(cmd->device->host)->dma_bounce_buffer); scsi_alloc_out_of_range = 1; } else { - amiga_chip_free (HDATA(cmd->host)->dma_bounce_buffer); + amiga_chip_free (HDATA(cmd->device->host)->dma_bounce_buffer); } - HDATA(cmd->host)->dma_bounce_buffer = - amiga_chip_alloc(HDATA(cmd->host)->dma_bounce_len, + HDATA(cmd->device->host)->dma_bounce_buffer = + amiga_chip_alloc(HDATA(cmd->device->host)->dma_bounce_len, "GVP II SCSI Bounce Buffer"); - if(!HDATA(cmd->host)->dma_bounce_buffer) + if(!HDATA(cmd->device->host)->dma_bounce_buffer) { - HDATA(cmd->host)->dma_bounce_len = 0; + HDATA(cmd->device->host)->dma_bounce_len = 0; return 1; } - addr = virt_to_bus(HDATA(cmd->host)->dma_bounce_buffer); - HDATA(cmd->host)->dma_buffer_pool = BUF_CHIP_ALLOCED; + addr = virt_to_bus(HDATA(cmd->device->host)->dma_bounce_buffer); + HDATA(cmd->device->host)->dma_buffer_pool = BUF_CHIP_ALLOCED; } if (!dir_in) { /* copy to bounce buffer for a write */ - memcpy (HDATA(cmd->host)->dma_bounce_buffer, + memcpy (HDATA(cmd->device->host)->dma_bounce_buffer, cmd->SCp.ptr, cmd->SCp.this_residual); } } @@ -125,11 +126,11 @@ static int dma_setup (Scsi_Cmnd *cmd, int dir_in) if (!dir_in) cntr |= GVP11_DMAC_DIR_WRITE; - HDATA(cmd->host)->dma_dir = dir_in; - DMA(cmd->host)->CNTR = cntr; + HDATA(cmd->device->host)->dma_dir = dir_in; + DMA(cmd->device->host)->CNTR = cntr; /* setup DMA *physical* address */ - DMA(cmd->host)->ACR = addr; + DMA(cmd->device->host)->ACR = addr; if (dir_in) /* invalidate any cache */ @@ -138,11 +139,11 @@ static int dma_setup (Scsi_Cmnd *cmd, int dir_in) /* push any dirty cache */ cache_push (addr, cmd->SCp.this_residual); - if ((bank_mask = (~HDATA(cmd->host)->dma_xfer_mask >> 18) & 0x01c0)) - DMA(cmd->host)->BANK = bank_mask & (addr >> 18); + if ((bank_mask = (~HDATA(cmd->device->host)->dma_xfer_mask >> 18) & 0x01c0)) + DMA(cmd->device->host)->BANK = bank_mask & (addr >> 18); /* start DMA */ - DMA(cmd->host)->ST_DMA = 1; + DMA(cmd->device->host)->ST_DMA = 1; /* return success */ return 0; diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index cfcfb247fd2b..1ad9639353c6 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -268,7 +268,7 @@ static Scsi_Host_Template *the_template = NULL; #define NEXTADDR(cmd) ((Scsi_Cmnd **)&((cmd)->host_scribble)) #define HOSTNO instance->host_no -#define H_NO(cmd) (cmd)->host->host_no +#define H_NO(cmd) (cmd)->device->host->host_no #define SGADDR(buffer) (void *)(((unsigned long)page_address((buffer)->page)) + \ (buffer)->offset) @@ -360,17 +360,17 @@ static void __init init_tags( void ) static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged ) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); - if (hostdata->busy[cmd->target] & (1 << cmd->lun)) + if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)) return( 1 ); if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) return( 0 ); - if (TagAlloc[cmd->target][cmd->lun].nr_allocated >= - TagAlloc[cmd->target][cmd->lun].queue_size ) { + if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >= + TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) { TAG_PRINTK( "scsi%d: target %d lun %d: no free tags\n", - H_NO(cmd), cmd->target, cmd->lun ); + H_NO(cmd), cmd->device->id, cmd->device->lun ); return( 1 ); } return( 0 ); @@ -384,7 +384,7 @@ static int is_lun_busy( Scsi_Cmnd *cmd, int should_be_tagged ) static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); /* If we or the target don't support tagged queuing, allocate the LUN for * an untagged command. @@ -392,19 +392,19 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) { cmd->tag = TAG_NONE; - hostdata->busy[cmd->target] |= (1 << cmd->lun); + hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); TAG_PRINTK( "scsi%d: target %d lun %d now allocated by untagged " - "command\n", H_NO(cmd), cmd->target, cmd->lun ); + "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun ); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; cmd->tag = find_first_zero_bit( &ta->allocated, MAX_TAGS ); set_bit( cmd->tag, &ta->allocated ); ta->nr_allocated++; TAG_PRINTK( "scsi%d: using tag %d for target %d lun %d " "(now %d tags in use)\n", - H_NO(cmd), cmd->tag, cmd->target, cmd->lun, + H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun, ta->nr_allocated ); } } @@ -416,23 +416,23 @@ static void cmd_get_tag( Scsi_Cmnd *cmd, int should_be_tagged ) static void cmd_free_tag( Scsi_Cmnd *cmd ) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); if (cmd->tag == TAG_NONE) { - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); TAG_PRINTK( "scsi%d: target %d lun %d untagged cmd finished\n", - H_NO(cmd), cmd->target, cmd->lun ); + H_NO(cmd), cmd->device->id, cmd->device->lun ); } else if (cmd->tag >= MAX_TAGS) { printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", H_NO(cmd), cmd->tag ); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; clear_bit( cmd->tag, &ta->allocated ); ta->nr_allocated--; TAG_PRINTK( "scsi%d: freed tag %d for target %d lun %d\n", - H_NO(cmd), cmd->tag, cmd->target, cmd->lun ); + H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun ); } } @@ -819,7 +819,7 @@ lprint_Scsi_Cmnd (Scsi_Cmnd *cmd, char *pos, char *buffer, int length) int i, s; unsigned char *command; SPRINTF("scsi%d: destination target %d, lun %d\n", - H_NO(cmd), cmd->target, cmd->lun); + H_NO(cmd), cmd->device->id, cmd->device->lun); SPRINTF(" command = "); command = cmd->cmnd; SPRINTF("%2d (0x%02x)", command[0], command[0]); @@ -911,7 +911,7 @@ static int NCR5380_init (struct Scsi_Host *instance, int flags) /* Only make static if a wrapper function is used */ static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); Scsi_Cmnd *tmp; unsigned long flags; @@ -943,15 +943,15 @@ static int NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) case WRITE: case WRITE_6: case WRITE_10: - hostdata->time_write[cmd->target] -= (jiffies - hostdata->timebase); - hostdata->bytes_write[cmd->target] += cmd->request_bufflen; + hostdata->time_write[cmd->device->id] -= (jiffies - hostdata->timebase); + hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen; hostdata->pendingw++; break; case READ: case READ_6: case READ_10: - hostdata->time_read[cmd->target] -= (jiffies - hostdata->timebase); - hostdata->bytes_read[cmd->target] += cmd->request_bufflen; + hostdata->time_read[cmd->device->id] -= (jiffies - hostdata->timebase); + hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen; hostdata->pendingr++; break; } @@ -1096,7 +1096,7 @@ static void NCR5380_main (void *bl) #ifdef SUPPORT_TAGS !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE) #else - !(hostdata->busy[tmp->target] & (1 << tmp->lun)) + !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun)) #endif ) { /* ++guenther: just to be sure, this must be atomic */ @@ -1350,15 +1350,15 @@ static void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd) case WRITE: case WRITE_6: case WRITE_10: - hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase); - /*hostdata->bytes_write[cmd->target] += cmd->request_bufflen;*/ + hostdata->time_write[cmd->device->id] += (jiffies - hostdata->timebase); + /*hostdata->bytes_write[cmd->device->id] += cmd->request_bufflen;*/ hostdata->pendingw--; break; case READ: case READ_6: case READ_10: - hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase); - /*hostdata->bytes_read[cmd->target] += cmd->request_bufflen;*/ + hostdata->time_read[cmd->device->id] += (jiffies - hostdata->timebase); + /*hostdata->bytes_read[cmd->device->id] += cmd->request_bufflen;*/ hostdata->pendingr--; break; } @@ -1519,7 +1519,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) * the host and target ID's on the SCSI bus. */ - NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->target))); + NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->device->id))); /* * Raise ATN while SEL is true before BSY goes false from arbitration, @@ -1572,7 +1572,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) udelay(1); - SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->target); + SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->device->id); /* * The SCSI specification calls for a 250 ms timeout for the actual @@ -1623,7 +1623,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) if (!(NCR5380_read(STATUS_REG) & SR_BSY)) { NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - if (hostdata->targets_present & (1 << cmd->target)) { + if (hostdata->targets_present & (1 << cmd->device->id)) { printk(KERN_ERR "scsi%d: weirdness\n", HOSTNO); if (hostdata->restart_select) printk(KERN_NOTICE "\trestart select\n"); @@ -1645,7 +1645,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) return 0; } - hostdata->targets_present |= (1 << cmd->target); + hostdata->targets_present |= (1 << cmd->device->id); /* * Since we followed the SCSI spec, and raised ATN while SEL @@ -1666,8 +1666,8 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) while (!(NCR5380_read(STATUS_REG) & SR_REQ)); SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n", - HOSTNO, cmd->target); - tmp[0] = IDENTIFY(1, cmd->lun); + HOSTNO, cmd->device->id); + tmp[0] = IDENTIFY(1, cmd->device->lun); #ifdef SUPPORT_TAGS if (cmd->tag != TAG_NONE) { @@ -1689,7 +1689,7 @@ static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag) /* XXX need to handle errors here */ hostdata->connected = cmd; #ifndef SUPPORT_TAGS - hostdata->busy[cmd->target] |= (1 << cmd->lun); + hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); #endif #ifdef SUN3_SCSI_VME dregs->csr |= CSR_INTR; @@ -2104,7 +2104,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) * polled-IO. */ printk(KERN_NOTICE "scsi%d: switching target %d " "lun %d to slow handshake\n", HOSTNO, - cmd->target, cmd->lun); + cmd->device->id, cmd->device->lun); cmd->device->borken = 1; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN); @@ -2162,7 +2162,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); LNK_PRINTK("scsi%d: target %d lun %d linked command " - "complete.\n", HOSTNO, cmd->target, cmd->lun); + "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun); /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); @@ -2175,7 +2175,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) if (!cmd->next_link) { printk(KERN_NOTICE "scsi%d: target %d lun %d " "linked command complete, no next_link\n", - HOSTNO, cmd->target, cmd->lun); + HOSTNO, cmd->device->id, cmd->device->lun); sink = 1; do_abort (instance); return; @@ -2188,7 +2188,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); LNK_PRINTK("scsi%d: target %d lun %d linked request " "done, calling scsi_done().\n", - HOSTNO, cmd->target, cmd->lun); + HOSTNO, cmd->device->id, cmd->device->lun); #ifdef NCR5380_STATS collect_stats(hostdata, cmd); #endif @@ -2202,7 +2202,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = NULL; QU_PRINTK("scsi%d: command for target %d, lun %d " - "completed\n", HOSTNO, cmd->target, cmd->lun); + "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef SUPPORT_TAGS cmd_free_tag( cmd ); if (status_byte(cmd->SCp.Status) == QUEUE_FULL) { @@ -2214,16 +2214,16 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) */ /* ++Andreas: the mid level code knows about QUEUE_FULL now. */ - TAG_ALLOC *ta = &TagAlloc[cmd->target][cmd->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; TAG_PRINTK("scsi%d: target %d lun %d returned " "QUEUE_FULL after %d commands\n", - HOSTNO, cmd->target, cmd->lun, + HOSTNO, cmd->device->id, cmd->device->lun, ta->nr_allocated); if (ta->queue_size > ta->nr_allocated) ta->nr_allocated = ta->queue_size; } #else - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif /* Enable reselect interrupts */ NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask); @@ -2313,12 +2313,12 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) * the command is treated as untagged further on. */ cmd->device->tagged_supported = 0; - hostdata->busy[cmd->target] |= (1 << cmd->lun); + hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); cmd->tag = TAG_NONE; TAG_PRINTK("scsi%d: target %d lun %d rejected " "QUEUE_TAG message; tagged queuing " "disabled\n", - HOSTNO, cmd->target, cmd->lun); + HOSTNO, cmd->device->id, cmd->device->lun); break; } break; @@ -2335,7 +2335,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) QU_PRINTK("scsi%d: command for target %d lun %d was " "moved from connected to the " "disconnected_queue\n", HOSTNO, - cmd->target, cmd->lun); + cmd->device->id, cmd->device->lun); /* * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. @@ -2437,13 +2437,13 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) } else if (tmp != EXTENDED_MESSAGE) printk(KERN_DEBUG "scsi%d: rejecting unknown " "message %02x from target %d, lun %d\n", - HOSTNO, tmp, cmd->target, cmd->lun); + HOSTNO, tmp, cmd->device->id, cmd->device->lun); else printk(KERN_DEBUG "scsi%d: rejecting unknown " "extended message " "code %02x, length %d from target %d, lun %d\n", HOSTNO, extended_msg[1], extended_msg[0], - cmd->target, cmd->lun); + cmd->device->id, cmd->device->lun); msgout = MESSAGE_REJECT; @@ -2461,7 +2461,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) #ifdef SUPPORT_TAGS cmd_free_tag( cmd ); #else - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif hostdata->connected = NULL; cmd->result = DID_ERROR << 16; @@ -2580,7 +2580,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) { - if ((target_mask == (1 << tmp->target)) && (lun == tmp->lun) + if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun) #ifdef SUPPORT_TAGS && (tag == tmp->tag) #endif @@ -2687,7 +2687,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) static int NCR5380_abort (Scsi_Cmnd *cmd) { - struct Scsi_Host *instance = cmd->host; + struct Scsi_Host *instance = cmd->device->host; SETUP_HOSTDATA(instance); Scsi_Cmnd *tmp, **prev; unsigned long flags; @@ -2737,7 +2737,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) #ifdef SUPPORT_TAGS cmd_free_tag( cmd ); #else - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif local_irq_restore(flags); cmd->scsi_done(cmd); @@ -2842,7 +2842,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) #ifdef SUPPORT_TAGS cmd_free_tag( tmp ); #else - hostdata->busy[cmd->target] &= ~(1 << cmd->lun); + hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); #endif local_irq_restore(flags); tmp->scsi_done(tmp); @@ -2879,7 +2879,7 @@ static int NCR5380_abort (Scsi_Cmnd *cmd) static int NCR5380_bus_reset( Scsi_Cmnd *cmd) { - SETUP_HOSTDATA(cmd->host); + SETUP_HOSTDATA(cmd->device->host); int i; unsigned long flags; #if 1 @@ -2887,7 +2887,7 @@ static int NCR5380_bus_reset( Scsi_Cmnd *cmd) #endif - NCR5380_print_status (cmd->host); + NCR5380_print_status (cmd->device->host); /* get in phase */ NCR5380_write( TARGET_COMMAND_REG, -- cgit v1.2.3 From 25de682c97637dc7d0f9f3fb98215071cd60ae56 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:05:14 -0800 Subject: [PATCH] Sun-3 NCR5380 SCSI warning Sun-3 NCR5380 SCSI: Kill warning. --- drivers/scsi/sun3_scsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/sun3_scsi.c b/drivers/scsi/sun3_scsi.c index 9ca0a90026a8..e3d27cc486dd 100644 --- a/drivers/scsi/sun3_scsi.c +++ b/drivers/scsi/sun3_scsi.c @@ -314,7 +314,7 @@ int sun3scsi_release (struct Scsi_Host *shpnt) if (shpnt->irq != IRQ_NONE) free_irq (shpnt->irq, NULL); - iounmap(sun3_scsi_regp); + iounmap((void *)sun3_scsi_regp); return 0; } -- cgit v1.2.3 From d4aa631a424bbf46740f3f4a027b3b7b46600b80 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:05:21 -0800 Subject: [PATCH] Amiga NCR53c7xx SCSI: use z_ioremap() Amiga NCR53c7xx SCSI: Use z_ioremap() to map Zorro space --- drivers/scsi/amiga7xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c index 715365d8c02c..89c454b2685f 100644 --- a/drivers/scsi/amiga7xx.c +++ b/drivers/scsi/amiga7xx.c @@ -86,7 +86,7 @@ int __init amiga7xx_detect(Scsi_Host_Template *tpnt) #ifdef CONFIG_WARPENGINE_SCSI case ZORRO_PROD_MACROSYSTEMS_WARP_ENGINE_40xx: if (request_mem_region(address+0x40000, 0x1000, "ncr53c710")) { - address = (unsigned long)ioremap(address, size); + address = (unsigned long)z_ioremap(address, size); options = OPTION_MEMORY_MAPPED | OPTION_DEBUG_TEST1 | OPTION_INTFLY | OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS | OPTION_DISCONNECT; @@ -102,7 +102,7 @@ int __init amiga7xx_detect(Scsi_Host_Template *tpnt) case ZORRO_PROD_CBM_A4091_1: case ZORRO_PROD_CBM_A4091_2: if (request_mem_region(address+0x800000, 0x1000, "ncr53c710")) { - address = (unsigned long)ioremap(address, size); + address = (unsigned long)z_ioremap(address, size); options = OPTION_MEMORY_MAPPED | OPTION_DEBUG_TEST1 | OPTION_INTFLY | OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS | OPTION_DISCONNECT; -- cgit v1.2.3 From 0ce4dfabf33d04068077d64a9f13e0c03e99686c Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:05:29 -0800 Subject: [PATCH] Amifb wrong interrupt Amiga frame buffer device: request the correct interrupt, so we no longer get spurious interrupts. The old code worked only by accident. To avoid flicker when updating the display parameters, we do not use the real vertical blank interrupt, but instead ask the Copper to generate an interrupt after the bitplane and sprite pointers have been set up at the beginning of each frame. --- drivers/video/amifb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 1a5410518e0b..06b0b403daf4 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1757,7 +1757,7 @@ default_chipset: ami_init_copper(); - if (request_irq(IRQ_AMIGA_VERTB, amifb_interrupt, 0, + if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0, "fb vertb handler", ¤tpar)) { err = -EBUSY; goto amifb_error; -- cgit v1.2.3 From dcaa9e3040cb860f3997e124cff8099a53dfff2a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:05:46 -0800 Subject: [PATCH] wd33c93 SCSI merge error Wd33c93 SCSI: Fix 2.5.64 merge error --- drivers/scsi/wd33c93.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 04c7d3907242..520f1d4f318c 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -1471,7 +1471,7 @@ reset_wd33c93(struct Scsi_Host *instance) int busycount = 0; extern void sgiwd93_reset(unsigned long); /* wait 'til the chip gets some time for us */ - while ((READ_AUX_STAT() & ASR_BSY) && busycount++ < 100) + while ((read_aux_stat(regs) & ASR_BSY) && busycount++ < 100) udelay (10); /* * there are scsi devices out there, which manage to lock up @@ -1481,7 +1481,7 @@ reset_wd33c93(struct Scsi_Host *instance) * does this for the SGI Indy, where this is possible */ /* still busy ? */ - if (READ_AUX_STAT() & ASR_BSY) + if (read_aux_stat(regs) & ASR_BSY) sgiwd93_reset(instance->base); /* yeah, give it the hard one */ } #endif -- cgit v1.2.3 From 26a734b5448f6b18daa32c5f5c3b2cf7a562e971 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:05:54 -0800 Subject: [PATCH] Sun-3 NCR5380 SCSI printk tags Sun-3 NCR5380 SCSI: Re-add accidentally deleted KERN_DEBUG tags. --- drivers/scsi/sun3_NCR5380.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 1ad9639353c6..89d3b02c8a05 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -616,11 +616,11 @@ static void NCR5380_print_phase(struct Scsi_Host *instance) status = NCR5380_read(STATUS_REG); if (!(status & SR_REQ)) - printk("scsi%d: REQ not asserted, phase unknown.\n", HOSTNO); + printk(KERN_DEBUG "scsi%d: REQ not asserted, phase unknown.\n", HOSTNO); else { for (i = 0; (phases[i].value != PHASE_UNKNOWN) && (phases[i].value != (status & PHASE_MASK)); ++i); - printk("scsi%d: phase %s\n", HOSTNO, phases[i].name); + printk(KERN_DEBUG "scsi%d: phase %s\n", HOSTNO, phases[i].name); } } -- cgit v1.2.3 From 524ed1c7c1be40fa0046cc4b5410cf4fc37458fa Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:06:23 -0800 Subject: [PATCH] console_initcall() return type Fix return type (must be int, not void) of *_console_init() after introduction of console_initcall() in 2.5.x. --- drivers/char/amiserial.c | 3 ++- drivers/char/decserial.c | 3 ++- drivers/char/serial167.c | 3 ++- drivers/char/serial_tx3912.c | 3 ++- drivers/char/sh-sci.c | 3 ++- drivers/char/vme_scc.c | 3 ++- 6 files changed, 12 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 37cbc60df1a6..187b8434fb69 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -2305,9 +2305,10 @@ static struct console sercons = { /* * Register console. */ -static void __init amiserial_console_init(void) +static int __init amiserial_console_init(void) { register_console(&sercons); + return 0; } console_initcall(amiserial_console_init); #endif diff --git a/drivers/char/decserial.c b/drivers/char/decserial.c index cd01044afd9d..aa1440934e95 100644 --- a/drivers/char/decserial.c +++ b/drivers/char/decserial.c @@ -75,7 +75,7 @@ __initcall(rs_init); /* serial_console_init handles the special case of starting * up the console on the serial port */ -static void __init decserial_console_init(void) +static int __init decserial_console_init(void) { #if defined(CONFIG_ZS) && defined(CONFIG_DZ) if (IOASIC) @@ -93,6 +93,7 @@ static void __init decserial_console_init(void) #endif #endif + return 0; } console_initcall(decserial_console_init); diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index dcd2d72c2579..1800ea9984dd 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -2836,7 +2836,7 @@ static struct console sercons = { }; -static void __init serial167_console_init(void) +static int __init serial167_console_init(void) { if (vme_brdtype == VME_TYPE_MVME166 || vme_brdtype == VME_TYPE_MVME167 || @@ -2844,6 +2844,7 @@ static void __init serial167_console_init(void) mvme167_serial_console_setup(0); register_console(&sercons); } + return 0; } console_initcall(serial167_console_init); diff --git a/drivers/char/serial_tx3912.c b/drivers/char/serial_tx3912.c index 394b0564aec9..ded61de976d2 100644 --- a/drivers/char/serial_tx3912.c +++ b/drivers/char/serial_tx3912.c @@ -1054,9 +1054,10 @@ static struct console sercons = { .index = -1 }; -static void __init tx3912_console_init(void) +static int __init tx3912_console_init(void) { register_console(&sercons); + return 0; } console_initcall(tx3912_console_init); diff --git a/drivers/char/sh-sci.c b/drivers/char/sh-sci.c index 5c2463b13eb6..8126a71d0b0b 100644 --- a/drivers/char/sh-sci.c +++ b/drivers/char/sh-sci.c @@ -1275,7 +1275,7 @@ static struct console sercons = { extern void sh_console_unregister (void); #endif -static void __init sci_console_init(void) +static int __init sci_console_init(void) { register_console(&sercons); #ifdef CONFIG_SH_EARLY_PRINTK @@ -1284,6 +1284,7 @@ static void __init sci_console_init(void) */ sh_console_unregister(); #endif + return 0; } console_initcall(sci_console_init); diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c index 3eb52370b48a..95cc54d04ed4 100644 --- a/drivers/char/vme_scc.c +++ b/drivers/char/vme_scc.c @@ -1091,7 +1091,7 @@ static struct console sercons = { }; -static void __init vme_scc_console_init(void) +static int __init vme_scc_console_init(void) { if (vme_brdtype == VME_TYPE_MVME147 || vme_brdtype == VME_TYPE_MVME162 || @@ -1099,5 +1099,6 @@ static void __init vme_scc_console_init(void) vme_brdtype == VME_TYPE_BVME4000 || vme_brdtype == VME_TYPE_BVME6000) register_console(&sercons); + return 0; } console_initcall(vme_scc_console_init); -- cgit v1.2.3 From 2a12c1bdeb1e8cf220304c25449e120f3669bbfd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 20 Mar 2003 06:06:32 -0800 Subject: [PATCH] Port amifb to new fbdev API Amiga frame buffer device: Port to the new fbdev API --- drivers/video/Makefile | 2 +- drivers/video/amifb.c | 1498 +++++++++++++++++++++++++++++++++--------------- drivers/video/c2p.c | 229 ++++++++ drivers/video/c2p.h | 16 + 4 files changed, 1269 insertions(+), 476 deletions(-) create mode 100644 drivers/video/c2p.c create mode 100644 drivers/video/c2p.h (limited to 'drivers') diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 610efa8be652..03f5dcef1d0a 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_PPC) += macmodes.o endif obj-$(CONFIG_FB_ACORN) += acornfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_AMIGA) += amifb.o +obj-$(CONFIG_FB_AMIGA) += amifb.o c2p.o obj-$(CONFIG_FB_PM2) += pm2fb.o obj-$(CONFIG_FB_PM3) += pm3fb.o obj-$(CONFIG_FB_APOLLO) += dnfb.o cfbfillrect.o cfbimgblt.o diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index 06b0b403daf4..5470149c077f 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1,7 +1,7 @@ /* * linux/drivers/video/amifb.c -- Amiga builtin chipset frame buffer device * - * Copyright (C) 1995 Geert Uytterhoeven + * Copyright (C) 1995-2003 Geert Uytterhoeven * * with work by Roman Zippel * @@ -62,10 +62,7 @@ #include #include -#include