提交 4796b71f 编写于 作者: D David Howells 提交者: David Howells

Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6

Conflicts:

	drivers/pcmcia/ds.c

Fix up merge failures with Linus's head and fix new compile failures.
Signed-Off-By: NDavid Howells <dhowells@redhat.com>
......@@ -1416,6 +1416,11 @@ and is between 256 and 4096 characters. It is defined in the file
scsi_logging= [SCSI]
scsi_mod.scan= [SCSI] sync (default) scans SCSI busses as they are
discovered. async scans them in kernel threads,
allowing boot to proceed. none ignores them, expecting
user space to do the scan.
selinux [SELINUX] Disable or enable SELinux at boot time.
Format: { "0" | "1" }
See security/selinux/Kconfig help text.
......
......@@ -375,7 +375,6 @@ Summary:
scsi_add_device - creates new scsi device (lu) instance
scsi_add_host - perform sysfs registration and set up transport class
scsi_adjust_queue_depth - change the queue depth on a SCSI device
scsi_assign_lock - replace default host_lock with given lock
scsi_bios_ptable - return copy of block device's partition table
scsi_block_requests - prevent further commands being queued to given host
scsi_deactivate_tcq - turn off tag command queueing
......@@ -488,20 +487,6 @@ void scsi_adjust_queue_depth(struct scsi_device * sdev, int tagged,
int tags)
/**
* scsi_assign_lock - replace default host_lock with given lock
* @shost: a pointer to a scsi host instance
* @lock: pointer to lock to replace host_lock for this host
*
* Returns nothing
*
* Might block: no
*
* Defined in: include/scsi/scsi_host.h .
**/
void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock)
/**
* scsi_bios_ptable - return copy of block device's partition table
* @dev: pointer to block device
......@@ -1366,17 +1351,11 @@ Locks
Each struct Scsi_Host instance has a spin_lock called struct
Scsi_Host::default_lock which is initialized in scsi_host_alloc() [found in
hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer
is initialized to point at default_lock with the scsi_assign_lock() function.
Thereafter lock and unlock operations performed by the mid level use the
struct Scsi_Host::host_lock pointer.
LLDs can override the use of struct Scsi_Host::default_lock by
using scsi_assign_lock(). The earliest opportunity to do this would
be in the detect() function after it has invoked scsi_register(). It
could be replaced by a coarser grain lock (e.g. per driver) or a
lock of equal granularity (i.e. per host). Using finer grain locks
(e.g. per SCSI device) may be possible by juggling locks in
queuecommand().
is initialized to point at default_lock. Thereafter lock and unlock
operations performed by the mid level use the struct Scsi_Host::host_lock
pointer. Previously drivers could override the host_lock pointer but
this is not allowed anymore.
Autosense
=========
......
......@@ -277,7 +277,7 @@ static int sg_io(struct file *file, request_queue_t *q,
if (rq->bio)
blk_queue_bounce(q, &rq->bio);
rq->timeout = (hdr->timeout * HZ) / 1000;
rq->timeout = jiffies_to_msecs(hdr->timeout);
if (!rq->timeout)
rq->timeout = q->sg_timeout;
if (!rq->timeout)
......
......@@ -154,19 +154,12 @@ static int pcmcia_init_one(struct pcmcia_device *pdev)
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(pdev, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(pdev, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(pdev, &tuple, &stk->parse));
pdev->conf.ConfigBase = stk->parse.config.base;
pdev->conf.Present = stk->parse.config.rmask[0];
/* See if we have a manufacturer identifier. Use it to set is_kme for
vendor quirks */
tuple.DesiredTuple = CISTPL_MANFID;
if (!pcmcia_get_first_tuple(pdev, &tuple) && !pcmcia_get_tuple_data(pdev, &tuple) && !pcmcia_parse_tuple(pdev, &tuple, &stk->parse))
is_kme = ((stk->parse.manfid.manf == MANFID_KME) && ((stk->parse.manfid.card == PRODID_KME_KXLC005_A) || (stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
is_kme = ((pdev->manf_id == MANFID_KME) &&
((pdev->card_id == PRODID_KME_KXLC005_A) ||
(pdev->card_id == PRODID_KME_KXLC005_B)));
/* Not sure if this is right... look up the current Vcc */
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(pdev, &stk->conf));
......@@ -356,8 +349,10 @@ static struct pcmcia_device_id pcmcia_devices[] = {
PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
......
......@@ -892,43 +892,10 @@ static void bluecard_detach(struct pcmcia_device *link)
}
static int first_tuple(struct pcmcia_device *handle, tuple_t *tuple, cisparse_t *parse)
{
int i;
i = pcmcia_get_first_tuple(handle, tuple);
if (i != CS_SUCCESS)
return CS_NO_MORE_ITEMS;
i = pcmcia_get_tuple_data(handle, tuple);
if (i != CS_SUCCESS)
return i;
return pcmcia_parse_tuple(handle, tuple, parse);
}
static int bluecard_config(struct pcmcia_device *link)
{
bluecard_info_t *info = link->priv;
tuple_t tuple;
u_short buf[256];
cisparse_t parse;
int i, n, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
}
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
int i, n;
link->conf.ConfigIndex = 0x20;
link->io.NumPorts1 = 64;
......@@ -966,9 +933,6 @@ static int bluecard_config(struct pcmcia_device *link)
return 0;
cs_failed:
cs_error(link, last_fn, last_ret);
failed:
bluecard_release(link);
return -ENODEV;
......
......@@ -713,22 +713,7 @@ static int bt3c_config(struct pcmcia_device *link)
u_short buf[256];
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
int i, j, try, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
}
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
int i, j, try;
/* First pass: look for a config entry that looks normal. */
tuple.TupleData = (cisdata_t *)buf;
......@@ -802,9 +787,6 @@ static int bt3c_config(struct pcmcia_device *link)
return 0;
cs_failed:
cs_error(link, last_fn, last_ret);
failed:
bt3c_release(link);
return -ENODEV;
......
......@@ -644,22 +644,7 @@ static int btuart_config(struct pcmcia_device *link)
u_short buf[256];
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
int i, j, try, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
}
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
int i, j, try;
/* First pass: look for a config entry that looks normal. */
tuple.TupleData = (cisdata_t *) buf;
......@@ -734,9 +719,6 @@ static int btuart_config(struct pcmcia_device *link)
return 0;
cs_failed:
cs_error(link, last_fn, last_ret);
failed:
btuart_release(link);
return -ENODEV;
......
......@@ -626,22 +626,7 @@ static int dtl1_config(struct pcmcia_device *link)
u_short buf[256];
cisparse_t parse;
cistpl_cftable_entry_t *cf = &parse.cftable_entry;
int i, last_ret, last_fn;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
/* Get configuration register information */
tuple.DesiredTuple = CISTPL_CONFIG;
last_ret = first_tuple(link, &tuple, &parse);
if (last_ret != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
}
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
int i;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0;
......@@ -690,9 +675,6 @@ static int dtl1_config(struct pcmcia_device *link)
return 0;
cs_failed:
cs_error(link, last_fn, last_ret);
failed:
dtl1_release(link);
return -ENODEV;
......
......@@ -1764,29 +1764,11 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
int rc;
/* read the config-tuples */
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetFirstTuple;
goto cs_failed;
}
if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetTupleData;
goto cs_failed;
}
if ((fail_rc =
pcmcia_parse_tuple(link, &tuple, &parse)) != CS_SUCCESS) {
fail_fn = ParseTuple;
goto cs_failed;
}
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
link->io.BasePort2 = 0;
link->io.NumPorts2 = 0;
link->io.Attributes2 = 0;
......@@ -1841,8 +1823,6 @@ static int cm4000_config(struct pcmcia_device * link, int devno)
return 0;
cs_failed:
cs_error(link, fail_fn, fail_rc);
cs_release:
cm4000_release(link);
return -ENODEV;
......@@ -1973,14 +1953,14 @@ static int __init cmm_init(void)
printk(KERN_INFO "%s\n", version);
cmm_class = class_create(THIS_MODULE, "cardman_4000");
if (!cmm_class)
return -1;
if (IS_ERR(cmm_class))
return PTR_ERR(cmm_class);
major = register_chrdev(0, DEVICE_NAME, &cm4000_fops);
if (major < 0) {
printk(KERN_WARNING MODULE_NAME
": could not get major number\n");
return -1;
return major;
}
rc = pcmcia_register_driver(&cm4000_driver);
......
......@@ -523,29 +523,11 @@ static int reader_config(struct pcmcia_device *link, int devno)
int fail_fn, fail_rc;
int rc;
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
if ((fail_rc = pcmcia_get_first_tuple(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetFirstTuple;
goto cs_failed;
}
if ((fail_rc = pcmcia_get_tuple_data(link, &tuple)) != CS_SUCCESS) {
fail_fn = GetTupleData;
goto cs_failed;
}
if ((fail_rc = pcmcia_parse_tuple(link, &tuple, &parse))
!= CS_SUCCESS) {
fail_fn = ParseTuple;
goto cs_failed;
}
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
link->io.BasePort2 = 0;
link->io.NumPorts2 = 0;
link->io.Attributes2 = 0;
......@@ -609,8 +591,6 @@ static int reader_config(struct pcmcia_device *link, int devno)
return 0;
cs_failed:
cs_error(link, fail_fn, fail_rc);
cs_release:
reader_release(link);
return -ENODEV;
......@@ -721,14 +701,14 @@ static int __init cm4040_init(void)
printk(KERN_INFO "%s\n", version);
cmx_class = class_create(THIS_MODULE, "cardman_4040");
if (!cmx_class)
return -1;
if (IS_ERR(cmx_class))
return PTR_ERR(cmx_class);
major = register_chrdev(0, DEVICE_NAME, &reader_fops);
if (major < 0) {
printk(KERN_WARNING MODULE_NAME
": could not get major number\n");
return -1;
return major;
}
rc = pcmcia_register_driver(&reader_driver);
......
......@@ -604,17 +604,10 @@ static int mgslpc_config(struct pcmcia_device *link)
if (debug_level >= DEBUG_LEVEL_INFO)
printk("mgslpc_config(0x%p)\n", link);
/* read CONFIG tuple to find its configuration registers */
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* get CIS configuration entry */
......
......@@ -192,20 +192,10 @@ static int ide_config(struct pcmcia_device *link)
tuple.TupleOffset = 0;
tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &stk->parse));
link->conf.ConfigBase = stk->parse.config.base;
link->conf.Present = stk->parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_MANFID;
if (!pcmcia_get_first_tuple(link, &tuple) &&
!pcmcia_get_tuple_data(link, &tuple) &&
!pcmcia_parse_tuple(link, &tuple, &stk->parse))
is_kme = ((stk->parse.manfid.manf == MANFID_KME) &&
((stk->parse.manfid.card == PRODID_KME_KXLC005_A) ||
(stk->parse.manfid.card == PRODID_KME_KXLC005_B)));
is_kme = ((link->manf_id == MANFID_KME) &&
((link->card_id == PRODID_KME_KXLC005_A) ||
(link->card_id == PRODID_KME_KXLC005_B)));
/* Not sure if this is right... look up the current Vcc */
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &stk->conf));
......@@ -408,8 +398,10 @@ static struct pcmcia_device_id ide_ids[] = {
PCMCIA_DEVICE_PROD_ID12("SMI VENDOR", "SMI PRODUCT", 0x30896c92, 0x703cc5f6),
PCMCIA_DEVICE_PROD_ID12("TOSHIBA", "MK2001MPL", 0xb4585a1a, 0x3489e003),
PCMCIA_DEVICE_PROD_ID1("TRANSCEND 512M ", 0xd0909443),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1),
PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8),
PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852),
PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918),
PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209),
PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e),
PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6),
......
......@@ -194,41 +194,11 @@ static int avmcs_config(struct pcmcia_device *link)
dev = link->priv;
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
do {
tuple.DesiredTuple = CISTPL_CONFIG;
i = pcmcia_get_first_tuple(link, &tuple);
if (i != CS_SUCCESS) break;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
i = pcmcia_get_tuple_data(link, &tuple);
if (i != CS_SUCCESS) break;
i = pcmcia_parse_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) break;
link->conf.ConfigBase = parse.config.base;
} while (0);
if (i != CS_SUCCESS) {
cs_error(link, ParseTuple, i);
return -ENODEV;
}
do {
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = 254;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
devname[0] = 0;
if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
sizeof(devname));
}
if (link->prod_id[1])
strlcpy(devname, link->prod_id[1], sizeof(devname));
/*
* find IO port
*/
......
......@@ -216,41 +216,11 @@ static int avma1cs_config(struct pcmcia_device *link)
DEBUG(0, "avma1cs_config(0x%p)\n", link);
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
do {
tuple.DesiredTuple = CISTPL_CONFIG;
i = pcmcia_get_first_tuple(link, &tuple);
if (i != CS_SUCCESS) break;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
i = pcmcia_get_tuple_data(link, &tuple);
if (i != CS_SUCCESS) break;
i = pcmcia_parse_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) break;
link->conf.ConfigBase = parse.config.base;
} while (0);
if (i != CS_SUCCESS) {
cs_error(link, ParseTuple, i);
return -ENODEV;
}
do {
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = 254;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
devname[0] = 0;
if( !first_tuple(link, &tuple, &parse) && parse.version_1.ns > 1 ) {
strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1],
sizeof(devname));
}
if (link->prod_id[1])
strlcpy(devname, link->prod_id[1], sizeof(devname));
/*
* find IO port
*/
......
......@@ -242,23 +242,6 @@ static int elsa_cs_config(struct pcmcia_device *link)
DEBUG(0, "elsa_config(0x%p)\n", link);
dev = link->priv;
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 255;
tuple.TupleOffset = 0;
tuple.Attributes = 0;
i = first_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
}
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
......
......@@ -233,20 +233,10 @@ static int sedlbauer_config(struct pcmcia_device *link)
DEBUG(0, "sedlbauer_config(0x%p)\n", link);
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
CS_CHECK(GetConfigurationInfo, pcmcia_get_configuration_info(link, &conf));
......
......@@ -232,23 +232,6 @@ static int teles_cs_config(struct pcmcia_device *link)
DEBUG(0, "teles_config(0x%p)\n", link);
dev = link->priv;
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 255;
tuple.TupleOffset = 0;
tuple.Attributes = 0;
i = first_tuple(link, &tuple, &parse);
if (i != CS_SUCCESS) {
last_fn = ParseTuple;
goto cs_failed;
}
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
......
......@@ -338,7 +338,6 @@ static int tc574_config(struct pcmcia_device *link)
struct net_device *dev = link->priv;
struct el3_private *lp = netdev_priv(dev);
tuple_t tuple;
cisparse_t parse;
unsigned short buf[32];
int last_fn, last_ret, i, j;
kio_addr_t ioaddr;
......@@ -350,17 +349,6 @@ static int tc574_config(struct pcmcia_device *link)
DEBUG(0, "3c574_config(0x%p)\n", link);
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
link->io.IOAddrLines = 16;
for (i = j = 0; j < 0x400; j += 0x20) {
link->io.BasePort1 = j ^ 0x300;
......@@ -382,6 +370,10 @@ static int tc574_config(struct pcmcia_device *link)
/* The 3c574 normally uses an EEPROM for configuration info, including
the hardware address. The future products may include a modem chip
and put the address in the CIS. */
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = 0x88;
if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
pcmcia_get_tuple_data(link, &tuple);
......@@ -397,12 +389,9 @@ static int tc574_config(struct pcmcia_device *link)
goto failed;
}
}
tuple.DesiredTuple = CISTPL_VERS_1;
if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS &&
pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS &&
pcmcia_parse_tuple(link, &tuple, &parse) == CS_SUCCESS) {
cardname = parse.version_1.str + parse.version_1.ofs[1];
} else
if (link->prod_id[1])
cardname = link->prod_id[1];
else
cardname = "3Com 3c574";
{
......
......@@ -253,7 +253,6 @@ static int tc589_config(struct pcmcia_device *link)
struct net_device *dev = link->priv;
struct el3_private *lp = netdev_priv(dev);
tuple_t tuple;
cisparse_t parse;
u16 buf[32], *phys_addr;
int last_fn, last_ret, i, j, multi = 0, fifo;
kio_addr_t ioaddr;
......@@ -263,26 +262,16 @@ static int tc589_config(struct pcmcia_device *link)
phys_addr = (u16 *)dev->dev_addr;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Is this a 3c562? */
tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON;
if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
(pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
if (le16_to_cpu(buf[0]) != MANFID_3COM)
/* Is this a 3c562? */
if (link->manf_id != MANFID_3COM)
printk(KERN_INFO "3c589_cs: hmmm, is this really a "
"3Com card??\n");
multi = (le16_to_cpu(buf[1]) == PRODID_3COM_3C562);
}
multi = (link->card_id == PRODID_3COM_3C562);
/* For the 3c562, the base address must be xx00-xx7f */
link->io.IOAddrLines = 16;
......
......@@ -299,11 +299,7 @@ static int axnet_config(struct pcmcia_device *link)
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
/* don't trust the CIS on this; Linksys got it wrong */
link->conf.Present = 0x63;
......
......@@ -249,12 +249,9 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static int com20020_config(struct pcmcia_device *link)
{
struct arcnet_local *lp;
tuple_t tuple;
cisparse_t parse;
com20020_dev_t *info;
struct net_device *dev;
int i, last_ret, last_fn;
u_char buf[64];
int ioaddr;
info = link->priv;
......@@ -264,16 +261,6 @@ static int com20020_config(struct pcmcia_device *link)
DEBUG(0, "com20020_config(0x%p)\n", link);
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
DEBUG(1,"arcnet: baseport1 is %Xh\n", link->io.BasePort1);
i = !CS_SUCCESS;
if (!link->io.BasePort1)
......
......@@ -342,7 +342,7 @@ static int fmvj18x_config(struct pcmcia_device *link)
tuple_t tuple;
cisparse_t parse;
u_short buf[32];
int i, last_fn, last_ret, ret;
int i, last_fn = 0, last_ret = 0, ret;
kio_addr_t ioaddr;
cardtype_t cardtype;
char *card_name = "unknown";
......@@ -350,21 +350,9 @@ static int fmvj18x_config(struct pcmcia_device *link)
DEBUG(0, "fmvj18x_config(0x%p)\n", link);
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = (u_char *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_FUNCE;
tuple.TupleOffset = 0;
if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) {
......@@ -374,17 +362,12 @@ static int fmvj18x_config(struct pcmcia_device *link)
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigIndex = parse.cftable_entry.index;
tuple.DesiredTuple = CISTPL_MANFID;
if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
else
buf[0] = 0xffff;
switch (le16_to_cpu(buf[0])) {
switch (link->manf_id) {
case MANFID_TDK:
cardtype = TDK;
if (le16_to_cpu(buf[1]) == PRODID_TDK_GN3410
|| le16_to_cpu(buf[1]) == PRODID_TDK_NP9610
|| le16_to_cpu(buf[1]) == PRODID_TDK_MN3200) {
if (link->card_id == PRODID_TDK_GN3410
|| link->card_id == PRODID_TDK_NP9610
|| link->card_id == PRODID_TDK_MN3200) {
/* MultiFunction Card */
link->conf.ConfigBase = 0x800;
link->conf.ConfigIndex = 0x47;
......@@ -395,11 +378,11 @@ static int fmvj18x_config(struct pcmcia_device *link)
cardtype = CONTEC;
break;
case MANFID_FUJITSU:
if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10302)
if (link->card_id == PRODID_FUJITSU_MBH10302)
/* RATOC REX-5588/9822/4886's PRODID are 0004(=MBH10302),
but these are MBH10304 based card. */
cardtype = MBH10304;
else if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304)
else if (link->card_id == PRODID_FUJITSU_MBH10304)
cardtype = MBH10304;
else
cardtype = LA501;
......@@ -409,14 +392,9 @@ static int fmvj18x_config(struct pcmcia_device *link)
}
} else {
/* old type card */
tuple.DesiredTuple = CISTPL_MANFID;
if (pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS)
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
else
buf[0] = 0xffff;
switch (le16_to_cpu(buf[0])) {
switch (link->manf_id) {
case MANFID_FUJITSU:
if (le16_to_cpu(buf[1]) == PRODID_FUJITSU_MBH10304) {
if (link->card_id == PRODID_FUJITSU_MBH10304) {
cardtype = XXX10304; /* MBH10304 with buggy CIS */
link->conf.ConfigIndex = 0x20;
} else {
......
......@@ -222,24 +222,12 @@ static int ibmtr_config(struct pcmcia_device *link)
ibmtr_dev_t *info = link->priv;
struct net_device *dev = info->dev;
struct tok_info *ti = netdev_priv(dev);
tuple_t tuple;
cisparse_t parse;
win_req_t req;
memreq_t mem;
int i, last_ret, last_fn;
u_char buf[64];
DEBUG(0, "ibmtr_config(0x%p)\n", link);
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.ConfigIndex = 0x61;
/* Determine if this is PRIMARY or ALTERNATE. */
......
......@@ -656,23 +656,12 @@ static int nmclan_config(struct pcmcia_device *link)
struct net_device *dev = link->priv;
mace_private *lp = netdev_priv(dev);
tuple_t tuple;
cisparse_t parse;
u_char buf[64];
int i, last_ret, last_fn;
kio_addr_t ioaddr;
DEBUG(0, "nmclan_config(0x%p)\n", link);
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
CS_CHECK(RequestIO, pcmcia_request_io(link, &link->io));
CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq));
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
......@@ -686,6 +675,7 @@ static int nmclan_config(struct pcmcia_device *link)
tuple.TupleData = buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.Attributes = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
memcpy(dev->dev_addr, tuple.TupleData, ETHER_ADDR_LEN);
......
......@@ -519,31 +519,15 @@ static int pcnet_config(struct pcmcia_device *link)
tuple_t tuple;
cisparse_t parse;
int i, last_ret, last_fn, start_pg, stop_pg, cm_offset;
int manfid = 0, prodid = 0, has_shmem = 0;
int has_shmem = 0;
u_short buf[64];
hw_info_t *hw_info;
DEBUG(0, "pcnet_config(0x%p)\n", link);
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON;
if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
(pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS)) {
manfid = le16_to_cpu(buf[0]);
prodid = le16_to_cpu(buf[1]);
}
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
......@@ -589,8 +573,8 @@ static int pcnet_config(struct pcmcia_device *link)
link->conf.Attributes |= CONF_ENABLE_SPKR;
link->conf.Status = CCSR_AUDIO_ENA;
}
if ((manfid == MANFID_IBM) &&
(prodid == PRODID_IBM_HOME_AND_AWAY))
if ((link->manf_id == MANFID_IBM) &&
(link->card_id == PRODID_IBM_HOME_AND_AWAY))
link->conf.ConfigIndex |= 0x10;
CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf));
......@@ -624,10 +608,10 @@ static int pcnet_config(struct pcmcia_device *link)
info->flags = hw_info->flags;
/* Check for user overrides */
info->flags |= (delay_output) ? DELAY_OUTPUT : 0;
if ((manfid == MANFID_SOCKET) &&
((prodid == PRODID_SOCKET_LPE) ||
(prodid == PRODID_SOCKET_LPE_CF) ||
(prodid == PRODID_SOCKET_EIO)))
if ((link->manf_id == MANFID_SOCKET) &&
((link->card_id == PRODID_SOCKET_LPE) ||
(link->card_id == PRODID_SOCKET_LPE_CF) ||
(link->card_id == PRODID_SOCKET_EIO)))
info->flags &= ~USE_BIG_BUF;
if (!use_big_buf)
info->flags &= ~USE_BIG_BUF;
......
......@@ -560,16 +560,8 @@ static int mhz_setup(struct pcmcia_device *link)
/* Read the station address from the CIS. It is stored as the last
(fourth) string in the Version 1 Version/ID tuple. */
tuple->DesiredTuple = CISTPL_VERS_1;
if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
/* Ugh -- the EM1144 card has two VERS_1 tuples!?! */
if (next_tuple(link, tuple, parse) != CS_SUCCESS)
first_tuple(link, tuple, parse);
if (parse->version_1.ns > 3) {
station_addr = parse->version_1.str + parse->version_1.ofs[3];
if (link->prod_id[3]) {
station_addr = link->prod_id[3];
if (cvt_ascii_address(dev, station_addr) == 0) {
rc = 0;
goto free_cfg_mem;
......@@ -744,15 +736,12 @@ static int smc_setup(struct pcmcia_device *link)
}
}
/* Try the third string in the Version 1 Version/ID tuple. */
tuple->DesiredTuple = CISTPL_VERS_1;
if (first_tuple(link, tuple, parse) != CS_SUCCESS) {
rc = -1;
goto free_cfg_mem;
}
station_addr = parse->version_1.str + parse->version_1.ofs[2];
if (cvt_ascii_address(dev, station_addr) == 0) {
rc = 0;
goto free_cfg_mem;
if (link->prod_id[2]) {
station_addr = link->prod_id[2];
if (cvt_ascii_address(dev, station_addr) == 0) {
rc = 0;
goto free_cfg_mem;
}
}
rc = -1;
......@@ -970,10 +959,6 @@ static int smc91c92_config(struct pcmcia_device *link)
{
struct net_device *dev = link->priv;
struct smc_private *smc = netdev_priv(dev);
struct smc_cfg_mem *cfg_mem;
tuple_t *tuple;
cisparse_t *parse;
u_char *buf;
char *name;
int i, j, rev;
kio_addr_t ioaddr;
......@@ -981,30 +966,8 @@ static int smc91c92_config(struct pcmcia_device *link)
DEBUG(0, "smc91c92_config(0x%p)\n", link);
cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);
if (!cfg_mem)
goto config_failed;
tuple = &cfg_mem->tuple;
parse = &cfg_mem->parse;
buf = cfg_mem->buf;
tuple->Attributes = tuple->TupleOffset = 0;
tuple->TupleData = (cisdata_t *)buf;
tuple->TupleDataMax = 64;
tuple->DesiredTuple = CISTPL_CONFIG;
i = first_tuple(link, tuple, parse);
CS_EXIT_TEST(i, ParseTuple, config_failed);
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
tuple->DesiredTuple = CISTPL_MANFID;
tuple->Attributes = TUPLE_RETURN_COMMON;
if (first_tuple(link, tuple, parse) == CS_SUCCESS) {
smc->manfid = parse->manfid.manf;
smc->cardid = parse->manfid.card;
}
smc->manfid = link->manf_id;
smc->cardid = link->card_id;
if ((smc->manfid == MANFID_OSITECH) &&
(smc->cardid != PRODID_OSITECH_SEVEN)) {
......@@ -1134,14 +1097,12 @@ static int smc91c92_config(struct pcmcia_device *link)
printk(KERN_NOTICE " No MII transceivers found!\n");
}
}
kfree(cfg_mem);
return 0;
config_undo:
unregister_netdev(dev);
config_failed: /* CS_EXIT_TEST() calls jump to here... */
smc91c92_release(link);
kfree(cfg_mem);
return -ENODEV;
} /* smc91c92_config */
......
......@@ -709,22 +709,11 @@ set_card_type(struct pcmcia_device *link, const void *s)
* Returns: true if this is a CE2
*/
static int
has_ce2_string(struct pcmcia_device * link)
has_ce2_string(struct pcmcia_device * p_dev)
{
tuple_t tuple;
cisparse_t parse;
u_char buf[256];
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = 254;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
if (!first_tuple(link, &tuple, &parse) && parse.version_1.ns > 2) {
if (strstr(parse.version_1.str + parse.version_1.ofs[2], "CE2"))
return 1;
}
return 0;
if (p_dev->prod_id[2] && strstr(p_dev->prod_id[2], "CE2"))
return 1;
return 0;
}
/****************
......@@ -794,13 +783,6 @@ xirc2ps_config(struct pcmcia_device * link)
goto failure;
}
/* get configuration stuff */
tuple.DesiredTuple = CISTPL_CONFIG;
if ((err=first_tuple(link, &tuple, &parse)))
goto cis_error;
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* get the ethernet address from the CIS */
tuple.DesiredTuple = CISTPL_FUNCE;
for (err = first_tuple(link, &tuple, &parse); !err;
......@@ -1064,8 +1046,6 @@ xirc2ps_config(struct pcmcia_device * link)
xirc2ps_release(link);
return -ENODEV;
cis_error:
printk(KNOT_XIRC "unable to parse CIS\n");
failure:
return -ENODEV;
} /* xirc2ps_config */
......
......@@ -219,21 +219,6 @@ static int airo_config(struct pcmcia_device *link)
dev = link->priv;
DEBUG(0, "airo_config(0x%p)\n", link);
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/*
In this loop, we scan the CIS for configuration table entries,
......@@ -247,6 +232,10 @@ static int airo_config(struct pcmcia_device *link)
these things without consulting the CIS, and most client drivers
will only use the CIS to fill in implementation-defined details.
*/
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
......
......@@ -243,17 +243,6 @@ static int atmel_config(struct pcmcia_device *link)
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/*
In this loop, we scan the CIS for configuration table entries,
each of which describes a valid card configuration, including
......
......@@ -293,15 +293,12 @@ static int sandisk_enable_wireless(struct net_device *dev)
goto done;
}
tuple.DesiredTuple = CISTPL_MANFID;
tuple.Attributes = TUPLE_RETURN_COMMON;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
if (pcmcia_get_first_tuple(hw_priv->link, &tuple) ||
pcmcia_get_tuple_data(hw_priv->link, &tuple) ||
pcmcia_parse_tuple(hw_priv->link, &tuple, parse) ||
parse->manfid.manf != 0xd601 || parse->manfid.card != 0x0101) {
if (hw_priv->link->manf_id != 0xd601 || hw_priv->link->card_id != 0x0101) {
/* No SanDisk manfid found */
ret = -ENODEV;
goto done;
......@@ -573,16 +570,10 @@ static int prism2_config(struct pcmcia_device *link)
}
memset(hw_priv, 0, sizeof(*hw_priv));
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, parse));
link->conf.ConfigBase = parse->config.base;
link->conf.Present = parse->config.rmask[0];
CS_CHECK(GetConfigurationInfo,
pcmcia_get_configuration_info(link, &conf));
......
......@@ -735,31 +735,13 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
static int netwave_pcmcia_config(struct pcmcia_device *link) {
struct net_device *dev = link->priv;
netwave_private *priv = netdev_priv(dev);
tuple_t tuple;
cisparse_t parse;
int i, j, last_ret, last_fn;
u_char buf[64];
win_req_t req;
memreq_t mem;
u_char __iomem *ramBase = NULL;
DEBUG(0, "netwave_pcmcia_config(0x%p)\n", link);
/*
This reads the card's CONFIG tuple to find its configuration
registers.
*/
tuple.Attributes = 0;
tuple.TupleData = (cisdata_t *) buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/*
* Try allocating IO ports. This tries a few fixed addresses.
* If you want, you can also read the card's config table to
......
......@@ -178,21 +178,6 @@ orinoco_cs_config(struct pcmcia_device *link)
cisparse_t parse;
void __iomem *mem;
/*
* This reads the card's CONFIG tuple to find its
* configuration registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo,
pcmcia_get_configuration_info(link, &conf));
......@@ -211,6 +196,10 @@ orinoco_cs_config(struct pcmcia_device *link)
* and most client drivers will only use the CIS to fill in
* implementation-defined details.
*/
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
......
......@@ -408,11 +408,8 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
#define MAX_TUPLE_SIZE 128
static int ray_config(struct pcmcia_device *link)
{
tuple_t tuple;
cisparse_t parse;
int last_fn = 0, last_ret = 0;
int i;
u_char buf[MAX_TUPLE_SIZE];
win_req_t req;
memreq_t mem;
struct net_device *dev = (struct net_device *)link->priv;
......@@ -420,29 +417,12 @@ static int ray_config(struct pcmcia_device *link)
DEBUG(1, "ray_config(0x%p)\n", link);
/* This reads the card's CONFIG tuple to find its configuration regs */
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = buf;
tuple.TupleDataMax = MAX_TUPLE_SIZE;
tuple.TupleOffset = 0;
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Determine card type and firmware version */
buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0;
tuple.DesiredTuple = CISTPL_VERS_1;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = buf;
tuple.TupleDataMax = MAX_TUPLE_SIZE;
tuple.TupleOffset = 2;
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
for (i=0; i<tuple.TupleDataLen - 4; i++)
if (buf[i] == 0) buf[i] = ' ';
printk(KERN_INFO "ray_cs Detected: %s\n",buf);
printk(KERN_INFO "ray_cs Detected: %s%s%s%s\n",
link->prod_id[0] ? link->prod_id[0] : " ",
link->prod_id[1] ? link->prod_id[1] : " ",
link->prod_id[2] ? link->prod_id[2] : " ",
link->prod_id[3] ? link->prod_id[3] : " ");
/* Now allocate an interrupt line. Note that this does not
actually assign a handler to the interrupt.
......
......@@ -647,21 +647,6 @@ spectrum_cs_config(struct pcmcia_device *link)
cisparse_t parse;
void __iomem *mem;
/*
* This reads the card's CONFIG tuple to find its
* configuration registers.
*/
tuple.DesiredTuple = CISTPL_CONFIG;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Look up the current Vcc */
CS_CHECK(GetConfigurationInfo,
pcmcia_get_configuration_info(link, &conf));
......@@ -681,6 +666,10 @@ spectrum_cs_config(struct pcmcia_device *link)
* implementation-defined details.
*/
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
tuple.TupleData = buf;
tuple.TupleDataMax = sizeof(buf);
tuple.TupleOffset = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
while (1) {
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
......
......@@ -3939,11 +3939,8 @@ wv_hw_reset(struct net_device * dev)
static inline int
wv_pcmcia_config(struct pcmcia_device * link)
{
tuple_t tuple;
cisparse_t parse;
struct net_device * dev = (struct net_device *) link->priv;
int i;
u_char buf[64];
win_req_t req;
memreq_t mem;
net_local * lp = netdev_priv(dev);
......@@ -3953,36 +3950,6 @@ wv_pcmcia_config(struct pcmcia_device * link)
printk(KERN_DEBUG "->wv_pcmcia_config(0x%p)\n", link);
#endif
/*
* This reads the card's CONFIG tuple to find its configuration
* registers.
*/
do
{
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
i = pcmcia_get_first_tuple(link, &tuple);
if(i != CS_SUCCESS)
break;
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleDataMax = 64;
tuple.TupleOffset = 0;
i = pcmcia_get_tuple_data(link, &tuple);
if(i != CS_SUCCESS)
break;
i = pcmcia_parse_tuple(link, &tuple, &parse);
if(i != CS_SUCCESS)
break;
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
}
while(0);
if(i != CS_SUCCESS)
{
cs_error(link, ParseTuple, i);
return FALSE;
}
do
{
i = pcmcia_request_io(link, &link->io);
......
......@@ -1966,25 +1966,10 @@ do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
*/
static int wl3501_config(struct pcmcia_device *link)
{
tuple_t tuple;
cisparse_t parse;
struct net_device *dev = link->priv;
int i = 0, j, last_fn, last_ret;
unsigned char bf[64];
struct wl3501_card *this;
/* This reads the card's CONFIG tuple to find its config registers. */
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
tuple.TupleData = bf;
tuple.TupleDataMax = sizeof(bf);
tuple.TupleOffset = 0;
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
/* Try allocating IO ports. This tries a few fixed addresses. If you
* want, you can also read the card's config table to pick addresses --
* see the serial driver for an example. */
......
......@@ -166,14 +166,6 @@ static int parport_config(struct pcmcia_device *link)
tuple.TupleData = (cisdata_t *)buf;
tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
tuple.Attributes = 0;
tuple.DesiredTuple = CISTPL_CONFIG;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple));
CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse));
link->conf.ConfigBase = parse.config.base;
link->conf.Present = parse.config.rmask[0];
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
tuple.Attributes = 0;
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
......@@ -263,6 +255,7 @@ void parport_cs_release(struct pcmcia_device *link)
static struct pcmcia_device_id parport_ids[] = {
PCMCIA_DEVICE_FUNC_ID(3),
PCMCIA_MFC_DEVICE_PROD_ID12(1,"Elan","Serial+Parallel Port: SP230",0x3beb8cf2,0xdb9e58bc),
PCMCIA_DEVICE_MANF_CARD(0x0137, 0x0003),
PCMCIA_DEVICE_NULL
};
......
......@@ -32,10 +32,11 @@
* A0..A10 work in each range; A23 indicates I/O space; A25 is CFRNW;
* some other bit in {A24,A22..A11} is nREG to flag memory access
* (vs attributes). So more than 2KB/region would just be waste.
* Note: These are offsets from the physical base address.
*/
#define CF_ATTR_PHYS (AT91_CF_BASE)
#define CF_IO_PHYS (AT91_CF_BASE + (1 << 23))
#define CF_MEM_PHYS (AT91_CF_BASE + 0x017ff800)
#define CF_ATTR_PHYS (0)
#define CF_IO_PHYS (1 << 23)
#define CF_MEM_PHYS (0x017ff800)
/*--------------------------------------------------------------------------*/
......@@ -48,6 +49,8 @@ struct at91_cf_socket {
struct platform_device *pdev;
struct at91_cf_data *board;
unsigned long phys_baseaddr;
};
#define SZ_2K (2 * SZ_1K)
......@@ -154,9 +157,8 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
/*
* Use 16 bit accesses unless/until we need 8-bit i/o space.
* Always set CSR4 ... PCMCIA won't always unmap things.
*/
csr = at91_sys_read(AT91_SMC_CSR(4)) & ~AT91_SMC_DBW;
csr = at91_sys_read(AT91_SMC_CSR(cf->board->chipselect)) & ~AT91_SMC_DBW;
/*
* NOTE: this CF controller ignores IOIS16, so we can't really do
......@@ -168,14 +170,14 @@ static int at91_cf_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
* some cards only like that way to get at the odd byte, despite
* CF 3.0 spec table 35 also giving the D8-D15 option.
*/
if (!(io->flags & (MAP_16BIT|MAP_AUTOSZ))) {
if (!(io->flags & (MAP_16BIT | MAP_AUTOSZ))) {
csr |= AT91_SMC_DBW_8;
pr_debug("%s: 8bit i/o bus\n", driver_name);
} else {
csr |= AT91_SMC_DBW_16;
pr_debug("%s: 16bit i/o bus\n", driver_name);
}
at91_sys_write(AT91_SMC_CSR(4), csr);
at91_sys_write(AT91_SMC_CSR(cf->board->chipselect), csr);
io->start = cf->socket.io_offset;
io->stop = io->start + SZ_2K - 1;
......@@ -194,11 +196,11 @@ at91_cf_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *map)
cf = container_of(s, struct at91_cf_socket, socket);
map->flags &= MAP_ACTIVE|MAP_ATTRIB|MAP_16BIT;
map->flags &= (MAP_ACTIVE | MAP_ATTRIB | MAP_16BIT);
if (map->flags & MAP_ATTRIB)
map->static_start = CF_ATTR_PHYS;
map->static_start = cf->phys_baseaddr + CF_ATTR_PHYS;
else
map->static_start = CF_MEM_PHYS;
map->static_start = cf->phys_baseaddr + CF_MEM_PHYS;
return 0;
}
......@@ -219,7 +221,6 @@ static int __init at91_cf_probe(struct platform_device *pdev)
struct at91_cf_socket *cf;
struct at91_cf_data *board = pdev->dev.platform_data;
struct resource *io;
unsigned int csa;
int status;
if (!board || !board->det_pin || !board->rst_pin)
......@@ -235,33 +236,11 @@ static int __init at91_cf_probe(struct platform_device *pdev)
cf->board = board;
cf->pdev = pdev;
cf->phys_baseaddr = io->start;
platform_set_drvdata(pdev, cf);
/* CF takes over CS4, CS5, CS6 */
csa = at91_sys_read(AT91_EBI_CSA);
at91_sys_write(AT91_EBI_CSA, csa | AT91_EBI_CS4A_SMC_COMPACTFLASH);
/* nWAIT is _not_ a default setting */
(void) at91_set_A_periph(AT91_PIN_PC6, 1); /* nWAIT */
/*
* Static memory controller timing adjustments.
* REVISIT: these timings are in terms of MCK cycles, so
* when MCK changes (cpufreq etc) so must these values...
*/
at91_sys_write(AT91_SMC_CSR(4),
AT91_SMC_ACSS_STD
| AT91_SMC_DBW_16
| AT91_SMC_BAT
| AT91_SMC_WSEN
| AT91_SMC_NWS_(32) /* wait states */
| AT91_SMC_RWSETUP_(6) /* setup time */
| AT91_SMC_RWHOLD_(4) /* hold time */
);
/* must be a GPIO; ergo must trigger on both edges */
status = request_irq(board->det_pin, at91_cf_irq,
IRQF_SAMPLE_RANDOM, driver_name, cf);
status = request_irq(board->det_pin, at91_cf_irq, 0, driver_name, cf);
if (status < 0)
goto fail0;
device_init_wakeup(&pdev->dev, 1);
......@@ -282,14 +261,18 @@ static int __init at91_cf_probe(struct platform_device *pdev)
cf->socket.pci_irq = NR_IRQS + 1;
/* pcmcia layer only remaps "real" memory not iospace */
cf->socket.io_offset = (unsigned long) ioremap(CF_IO_PHYS, SZ_2K);
if (!cf->socket.io_offset)
cf->socket.io_offset = (unsigned long) ioremap(cf->phys_baseaddr + CF_IO_PHYS, SZ_2K);
if (!cf->socket.io_offset) {
status = -ENXIO;
goto fail1;
}
/* reserve CS4, CS5, and CS6 regions; but use just CS4 */
/* reserve chip-select regions */
if (!request_mem_region(io->start, io->end + 1 - io->start,
driver_name))
driver_name)) {
status = -ENXIO;
goto fail1;
}
pr_info("%s: irqs det #%d, io #%d\n", driver_name,
board->det_pin, board->irq_pin);
......@@ -319,9 +302,7 @@ static int __init at91_cf_probe(struct platform_device *pdev)
fail0a:
device_init_wakeup(&pdev->dev, 0);
free_irq(board->det_pin, cf);
device_init_wakeup(&pdev->dev, 0);
fail0:
at91_sys_write(AT91_EBI_CSA, csa);
kfree(cf);
return status;
}
......@@ -331,19 +312,15 @@ static int __exit at91_cf_remove(struct platform_device *pdev)
struct at91_cf_socket *cf = platform_get_drvdata(pdev);
struct at91_cf_data *board = cf->board;
struct resource *io = cf->socket.io[0].res;
unsigned int csa;
pcmcia_unregister_socket(&cf->socket);
if (board->irq_pin)
free_irq(board->irq_pin, cf);
free_irq(board->det_pin, cf);
device_init_wakeup(&pdev->dev, 0);
free_irq(board->det_pin, cf);
iounmap((void __iomem *) cf->socket.io_offset);
release_mem_region(io->start, io->end + 1 - io->start);
csa = at91_sys_read(AT91_EBI_CSA);
at91_sys_write(AT91_EBI_CSA, csa & ~AT91_EBI_CS4A);
kfree(cf);
return 0;
}
......
......@@ -135,7 +135,7 @@ int pccard_get_status(struct pcmcia_socket *s, struct pcmcia_device *p_dev, cs_s
struct pcmcia_callback{
struct module *owner;
int (*event) (struct pcmcia_socket *s, event_t event, int priority);
void (*requery) (struct pcmcia_socket *s);
void (*requery) (struct pcmcia_socket *s, int new_cis);
int (*suspend) (struct pcmcia_socket *s);
int (*resume) (struct pcmcia_socket *s);
};
......
......@@ -231,65 +231,6 @@ static void pcmcia_check_driver(struct pcmcia_driver *p_drv)
}
#ifdef CONFIG_PCMCIA_LOAD_CIS
/**
* pcmcia_load_firmware - load CIS from userspace if device-provided is broken
* @dev - the pcmcia device which needs a CIS override
* @filename - requested filename in /lib/firmware/
*
* This uses the in-kernel firmware loading mechanism to use a "fake CIS" if
* the one provided by the card is broken. The firmware files reside in
* /lib/firmware/ in userspace.
*/
static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
struct pcmcia_socket *s = dev->socket;
const struct firmware *fw;
char path[20];
int ret=-ENOMEM;
cisdump_t *cis;
if (!filename)
return -EINVAL;
ds_dbg(1, "trying to load firmware %s\n", filename);
if (strlen(filename) > 14)
return -EINVAL;
snprintf(path, 20, "%s", filename);
if (request_firmware(&fw, path, &dev->dev) == 0) {
if (fw->size >= CISTPL_MAX_CIS_SIZE)
goto release;
cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
if (!cis)
goto release;
cis->Length = fw->size + 1;
memcpy(cis->Data, fw->data, fw->size);
if (!pcmcia_replace_cis(s, cis))
ret = 0;
}
release:
release_firmware(fw);
return (ret);
}
#else /* !CONFIG_PCMCIA_LOAD_CIS */
static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
return -ENODEV;
}
#endif
/*======================================================================*/
......@@ -309,6 +250,8 @@ int pcmcia_register_driver(struct pcmcia_driver *driver)
driver->drv.bus = &pcmcia_bus_type;
driver->drv.owner = driver->owner;
ds_dbg(3, "registering driver %s\n", driver->drv.name);
return driver_register(&driver->drv);
}
EXPORT_SYMBOL(pcmcia_register_driver);
......@@ -318,6 +261,7 @@ EXPORT_SYMBOL(pcmcia_register_driver);
*/
void pcmcia_unregister_driver(struct pcmcia_driver *driver)
{
ds_dbg(3, "unregistering driver %s\n", driver->drv.name);
driver_unregister(&driver->drv);
}
EXPORT_SYMBOL(pcmcia_unregister_driver);
......@@ -343,23 +287,27 @@ void pcmcia_put_dev(struct pcmcia_device *p_dev)
static void pcmcia_release_function(struct kref *ref)
{
struct config_t *c = container_of(ref, struct config_t, ref);
ds_dbg(1, "releasing config_t\n");
kfree(c);
}
static void pcmcia_release_dev(struct device *dev)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
ds_dbg(1, "releasing dev %p\n", p_dev);
ds_dbg(1, "releasing device %s\n", p_dev->dev.bus_id);
pcmcia_put_socket(p_dev->socket);
kfree(p_dev->devname);
kref_put(&p_dev->function_config->ref, pcmcia_release_function);
kfree(p_dev);
}
static void pcmcia_add_pseudo_device(struct pcmcia_socket *s)
static void pcmcia_add_device_later(struct pcmcia_socket *s, int mfc)
{
if (!s->pcmcia_state.device_add_pending) {
ds_dbg(1, "scheduling to add %s secondary"
" device to %d\n", mfc ? "mfc" : "pfc", s->sock);
s->pcmcia_state.device_add_pending = 1;
s->pcmcia_state.mfc_pfc = mfc;
schedule_work(&s->device_add);
}
return;
......@@ -371,6 +319,7 @@ static int pcmcia_device_probe(struct device * dev)
struct pcmcia_driver *p_drv;
struct pcmcia_device_id *did;
struct pcmcia_socket *s;
cistpl_config_t cis_config;
int ret = 0;
dev = get_device(dev);
......@@ -381,15 +330,33 @@ static int pcmcia_device_probe(struct device * dev)
p_drv = to_pcmcia_drv(dev->driver);
s = p_dev->socket;
ds_dbg(1, "trying to bind %s to %s\n", p_dev->dev.bus_id,
p_drv->drv.name);
if ((!p_drv->probe) || (!p_dev->function_config) ||
(!try_module_get(p_drv->owner))) {
ret = -EINVAL;
goto put_dev;
}
/* set up some more device information */
ret = pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_CONFIG,
&cis_config);
if (!ret) {
p_dev->conf.ConfigBase = cis_config.base;
p_dev->conf.Present = cis_config.rmask[0];
} else {
printk(KERN_INFO "pcmcia: could not parse base and rmask0 of CIS\n");
p_dev->conf.ConfigBase = 0;
p_dev->conf.Present = 0;
}
ret = p_drv->probe(p_dev);
if (ret)
if (ret) {
ds_dbg(1, "binding %s to %s failed with %d\n",
p_dev->dev.bus_id, p_drv->drv.name, ret);
goto put_module;
}
/* handle pseudo multifunction devices:
* there are at most two pseudo multifunction devices.
......@@ -400,7 +367,7 @@ static int pcmcia_device_probe(struct device * dev)
did = p_dev->dev.driver_data;
if (did && (did->match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO) &&
(p_dev->socket->device_count == 1) && (p_dev->device_no == 0))
pcmcia_add_pseudo_device(p_dev->socket);
pcmcia_add_device_later(p_dev->socket, 0);
put_module:
if (ret)
......@@ -421,8 +388,8 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le
struct pcmcia_device *tmp;
unsigned long flags;
ds_dbg(2, "unbind_request(%d)\n", s->sock);
ds_dbg(2, "pcmcia_card_remove(%d) %s\n", s->sock,
leftover ? leftover->devname : "");
if (!leftover)
s->device_count = 0;
......@@ -439,6 +406,7 @@ static void pcmcia_card_remove(struct pcmcia_socket *s, struct pcmcia_device *le
p_dev->_removed=1;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
ds_dbg(2, "unregistering device %s\n", p_dev->dev.bus_id);
device_unregister(&p_dev->dev);
}
......@@ -455,6 +423,8 @@ static int pcmcia_device_remove(struct device * dev)
p_dev = to_pcmcia_dev(dev);
p_drv = to_pcmcia_drv(dev->driver);
ds_dbg(1, "removing device %s\n", p_dev->dev.bus_id);
/* If we're removing the primary module driving a
* pseudo multi-function card, we need to unbind
* all devices
......@@ -587,8 +557,10 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
mutex_lock(&device_add_lock);
/* max of 2 devices per card */
if (s->device_count == 2)
ds_dbg(3, "adding device to %d, function %d\n", s->sock, function);
/* max of 4 devices per card */
if (s->device_count == 4)
goto err_put;
p_dev = kzalloc(sizeof(struct pcmcia_device), GFP_KERNEL);
......@@ -598,8 +570,6 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
p_dev->socket = s;
p_dev->device_no = (s->device_count++);
p_dev->func = function;
if (s->functions <= function)
s->functions = function + 1;
p_dev->dev.bus = &pcmcia_bus_type;
p_dev->dev.parent = s->dev.dev;
......@@ -610,8 +580,8 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
if (!p_dev->devname)
goto err_free;
sprintf (p_dev->devname, "pcmcia%s", p_dev->dev.bus_id);
ds_dbg(3, "devname is %s\n", p_dev->devname);
/* compat */
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
/*
......@@ -631,6 +601,7 @@ struct pcmcia_device * pcmcia_device_add(struct pcmcia_socket *s, unsigned int f
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
if (!p_dev->function_config) {
ds_dbg(3, "creating config_t for %s\n", p_dev->dev.bus_id);
p_dev->function_config = kzalloc(sizeof(struct config_t),
GFP_KERNEL);
if (!p_dev->function_config)
......@@ -674,11 +645,16 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
unsigned int no_funcs, i;
int ret = 0;
if (!(s->resource_setup_done))
if (!(s->resource_setup_done)) {
ds_dbg(3, "no resources available, delaying card_add\n");
return -EAGAIN; /* try again, but later... */
}
if (pcmcia_validate_mem(s))
if (pcmcia_validate_mem(s)) {
ds_dbg(3, "validating mem resources failed, "
"delaying card_add\n");
return -EAGAIN; /* try again, but later... */
}
ret = pccard_validate_cis(s, BIND_FN_ALL, &cisinfo);
if (ret || !cisinfo.Chains) {
......@@ -690,6 +666,7 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
no_funcs = mfc.nfn;
else
no_funcs = 1;
s->functions = no_funcs;
for (i=0; i < no_funcs; i++)
pcmcia_device_add(s, i);
......@@ -698,39 +675,50 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
}
static void pcmcia_delayed_add_pseudo_device(struct work_struct *work)
static void pcmcia_delayed_add_device(struct work_struct *work)
{
struct pcmcia_socket *s =
container_of(work, struct pcmcia_socket, device_add);
pcmcia_device_add(s, 0);
ds_dbg(1, "adding additional device to %d\n", s->sock);
pcmcia_device_add(s, s->pcmcia_state.mfc_pfc);
s->pcmcia_state.device_add_pending = 0;
s->pcmcia_state.mfc_pfc = 0;
}
static int pcmcia_requery(struct device *dev, void * _data)
{
struct pcmcia_device *p_dev = to_pcmcia_dev(dev);
if (!p_dev->dev.driver)
if (!p_dev->dev.driver) {
ds_dbg(1, "update device information for %s\n",
p_dev->dev.bus_id);
pcmcia_device_query(p_dev);
}
return 0;
}
static void pcmcia_bus_rescan(struct pcmcia_socket *skt)
static void pcmcia_bus_rescan(struct pcmcia_socket *skt, int new_cis)
{
int no_devices=0;
int no_devices = 0;
int ret = 0;
unsigned long flags;
/* must be called with skt_mutex held */
ds_dbg(0, "re-scanning socket %d\n", skt->sock);
spin_lock_irqsave(&pcmcia_dev_list_lock, flags);
if (list_empty(&skt->devices_list))
no_devices=1;
no_devices = 1;
spin_unlock_irqrestore(&pcmcia_dev_list_lock, flags);
/* If this is because of a CIS override, start over */
if (new_cis && !no_devices)
pcmcia_card_remove(skt, NULL);
/* if no devices were added for this socket yet because of
* missing resource information or other trouble, we need to
* do this now. */
if (no_devices) {
if (no_devices || new_cis) {
ret = pcmcia_card_add(skt);
if (ret)
return;
......@@ -748,6 +736,97 @@ static void pcmcia_bus_rescan(struct pcmcia_socket *skt)
printk(KERN_INFO "pcmcia: bus_rescan_devices failed\n");
}
#ifdef CONFIG_PCMCIA_LOAD_CIS
/**
* pcmcia_load_firmware - load CIS from userspace if device-provided is broken
* @dev - the pcmcia device which needs a CIS override
* @filename - requested filename in /lib/firmware/
*
* This uses the in-kernel firmware loading mechanism to use a "fake CIS" if
* the one provided by the card is broken. The firmware files reside in
* /lib/firmware/ in userspace.
*/
static int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
struct pcmcia_socket *s = dev->socket;
const struct firmware *fw;
char path[20];
int ret = -ENOMEM;
int no_funcs;
int old_funcs;
cisdump_t *cis;
cistpl_longlink_mfc_t mfc;
if (!filename)
return -EINVAL;
ds_dbg(1, "trying to load CIS file %s\n", filename);
if (strlen(filename) > 14) {
printk(KERN_WARNING "pcmcia: CIS filename is too long\n");
return -EINVAL;
}
snprintf(path, 20, "%s", filename);
if (request_firmware(&fw, path, &dev->dev) == 0) {
if (fw->size >= CISTPL_MAX_CIS_SIZE) {
ret = -EINVAL;
printk(KERN_ERR "pcmcia: CIS override is too big\n");
goto release;
}
cis = kzalloc(sizeof(cisdump_t), GFP_KERNEL);
if (!cis) {
ret = -ENOMEM;
goto release;
}
cis->Length = fw->size + 1;
memcpy(cis->Data, fw->data, fw->size);
if (!pcmcia_replace_cis(s, cis))
ret = 0;
else {
printk(KERN_ERR "pcmcia: CIS override failed\n");
goto release;
}
/* update information */
pcmcia_device_query(dev);
/* does this cis override add or remove functions? */
old_funcs = s->functions;
if (!pccard_read_tuple(s, BIND_FN_ALL, CISTPL_LONGLINK_MFC, &mfc))
no_funcs = mfc.nfn;
else
no_funcs = 1;
s->functions = no_funcs;
if (old_funcs > no_funcs)
pcmcia_card_remove(s, dev);
else if (no_funcs > old_funcs)
pcmcia_add_device_later(s, 1);
}
release:
release_firmware(fw);
return (ret);
}
#else /* !CONFIG_PCMCIA_LOAD_CIS */
static inline int pcmcia_load_firmware(struct pcmcia_device *dev, char * filename)
{
return -ENODEV;
}
#endif
static inline int pcmcia_devmatch(struct pcmcia_device *dev,
struct pcmcia_device_id *did)
{
......@@ -814,11 +893,14 @@ static inline int pcmcia_devmatch(struct pcmcia_device *dev,
* after it has re-checked that there is no possible module
* with a prod_id/manf_id/card_id match.
*/
ds_dbg(0, "skipping FUNC_ID match for %s until userspace "
"interaction\n", dev->dev.bus_id);
if (!dev->allow_func_id_match)
return 0;
}
if (did->match_flags & PCMCIA_DEV_ID_MATCH_FAKE_CIS) {
ds_dbg(0, "device %s needs a fake CIS\n", dev->dev.bus_id);
if (!dev->socket->fake_cis)
pcmcia_load_firmware(dev, did->cisfile);
......@@ -848,13 +930,21 @@ static int pcmcia_bus_match(struct device * dev, struct device_driver * drv) {
#ifdef CONFIG_PCMCIA_IOCTL
/* matching by cardmgr */
if (p_dev->cardmgr == p_drv)
if (p_dev->cardmgr == p_drv) {
ds_dbg(0, "cardmgr matched %s to %s\n", dev->bus_id,
drv->name);
return 1;
}
#endif
while (did && did->match_flags) {
if (pcmcia_devmatch(p_dev, did))
ds_dbg(3, "trying to match %s to %s\n", dev->bus_id,
drv->name);
if (pcmcia_devmatch(p_dev, did)) {
ds_dbg(0, "matched %s to %s\n", dev->bus_id,
drv->name);
return 1;
}
did++;
}
......@@ -1045,6 +1135,8 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
struct pcmcia_driver *p_drv = NULL;
int ret = 0;
ds_dbg(2, "suspending %s\n", dev->bus_id);
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
......@@ -1053,12 +1145,18 @@ static int pcmcia_dev_suspend(struct device * dev, pm_message_t state)
if (p_drv->suspend) {
ret = p_drv->suspend(p_dev);
if (ret)
if (ret) {
printk(KERN_ERR "pcmcia: device %s (driver %s) did "
"not want to go to sleep (%d)\n",
p_dev->devname, p_drv->drv.name, ret);
goto out;
}
}
if (p_dev->device_no == p_dev->func)
if (p_dev->device_no == p_dev->func) {
ds_dbg(2, "releasing configuration for %s\n", dev->bus_id);
pcmcia_release_configuration(p_dev);
}
out:
if (!ret)
......@@ -1073,6 +1171,8 @@ static int pcmcia_dev_resume(struct device * dev)
struct pcmcia_driver *p_drv = NULL;
int ret = 0;
ds_dbg(2, "resuming %s\n", dev->bus_id);
if (dev->driver)
p_drv = to_pcmcia_drv(dev->driver);
......@@ -1080,6 +1180,7 @@ static int pcmcia_dev_resume(struct device * dev)
goto out;
if (p_dev->device_no == p_dev->func) {
ds_dbg(2, "requesting configuration for %s\n", dev->bus_id);
ret = pcmcia_request_configuration(p_dev, &p_dev->conf);
if (ret)
goto out;
......@@ -1121,12 +1222,14 @@ static int pcmcia_bus_resume_callback(struct device *dev, void * _data)
static int pcmcia_bus_resume(struct pcmcia_socket *skt)
{
ds_dbg(2, "resuming socket %d\n", skt->sock);
bus_for_each_dev(&pcmcia_bus_type, NULL, skt, pcmcia_bus_resume_callback);
return 0;
}
static int pcmcia_bus_suspend(struct pcmcia_socket *skt)
{
ds_dbg(2, "suspending socket %d\n", skt->sock);
if (bus_for_each_dev(&pcmcia_bus_type, NULL, skt,
pcmcia_bus_suspend_callback)) {
pcmcia_bus_resume(skt);
......@@ -1247,7 +1350,7 @@ static int __devinit pcmcia_bus_add_socket(struct class_device *class_dev,
init_waitqueue_head(&socket->queue);
#endif
INIT_LIST_HEAD(&socket->devices_list);
INIT_WORK(&socket->device_add, pcmcia_delayed_add_pseudo_device);
INIT_WORK(&socket->device_add, pcmcia_delayed_add_device);
memset(&socket->pcmcia_state, 0, sizeof(u8));
socket->device_count = 0;
......
......@@ -398,7 +398,7 @@ static irqreturn_t pcc_interrupt(int irq, void *dev)
static void pcc_interrupt_wrapper(u_long data)
{
debug(3, "m32r_cfc: pcc_interrupt_wrapper:\n");
pcc_interrupt(0, NULL, NULL);
pcc_interrupt(0, NULL);
init_timer(&poll_timer);
poll_timer.expires = jiffies + poll_interval;
add_timer(&poll_timer);
......
......@@ -594,7 +594,12 @@ static int ds_ioctl(struct inode * inode, struct file * file,
err = ret = 0;
if (cmd & IOC_IN) __copy_from_user((char *)buf, uarg, size);
if (cmd & IOC_IN) {
if (__copy_from_user((char *)buf, uarg, size)) {
err = -EFAULT;
goto free_out;
}
}
switch (cmd) {
case DS_ADJUST_RESOURCE_INFO:
......
......@@ -581,10 +581,10 @@ static irqreturn_t pd6729_test(int irq, void *dev)
return IRQ_HANDLED;
}
static int pd6729_check_irq(int irq, int flags)
static int pd6729_check_irq(int irq)
{
if (request_irq(irq, pd6729_test, flags, "x", pd6729_test) != 0)
return -1;
if (request_irq(irq, pd6729_test, IRQF_PROBE_SHARED, "x", pd6729_test)
!= 0) return -1;
free_irq(irq, pd6729_test);
return 0;
}
......@@ -610,7 +610,7 @@ static u_int __devinit pd6729_isa_scan(void)
/* just find interrupts that aren't in use */
for (i = 0; i < 16; i++)
if ((mask0 & (1 << i)) && (pd6729_check_irq(i, 0) == 0))
if ((mask0 & (1 << i)) && (pd6729_check_irq(i) == 0))
mask |= (1 << i);
printk(KERN_INFO "pd6729: ISA irqs = ");
......
......@@ -188,7 +188,7 @@ static ssize_t pccard_store_resource(struct class_device *dev, const char *buf,
(s->state & SOCKET_PRESENT) &&
!(s->state & SOCKET_CARDBUS)) {
if (try_module_get(s->callback->owner)) {
s->callback->requery(s);
s->callback->requery(s, 0);
module_put(s->callback->owner);
}
}
......@@ -325,7 +325,7 @@ static ssize_t pccard_store_cis(struct kobject *kobj, char *buf, loff_t off, siz
if ((s->callback) && (s->state & SOCKET_PRESENT) &&
!(s->state & SOCKET_CARDBUS)) {
if (try_module_get(s->callback->owner)) {
s->callback->requery(s);
s->callback->requery(s, 1);
module_put(s->callback->owner);
}
}
......
......@@ -622,8 +622,10 @@ NCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,
dma_unmap_single(hostdata->dev, slot->dma_handle, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
/* restore the old result if the request sense was
* successful */
if(result == 0)
if (result == 0)
result = cmnd[7];
/* restore the original length */
SCp->cmd_len = cmnd[8];
} else
NCR_700_unmap(hostdata, SCp, slot);
......@@ -1007,6 +1009,9 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp,
* of the command */
cmnd[6] = NCR_700_INTERNAL_SENSE_MAGIC;
cmnd[7] = hostdata->status[0];
cmnd[8] = SCp->cmd_len;
SCp->cmd_len = 6; /* command length for
* REQUEST_SENSE */
slot->pCmd = dma_map_single(hostdata->dev, cmnd, MAX_COMMAND_SIZE, DMA_TO_DEVICE);
slot->dma_handle = dma_map_single(hostdata->dev, SCp->sense_buffer, sizeof(SCp->sense_buffer), DMA_FROM_DEVICE);
slot->SG[0].ins = bS_to_host(SCRIPT_MOVE_DATA_IN | sizeof(SCp->sense_buffer));
......
......@@ -2186,21 +2186,21 @@ static int __init BusLogic_init(void)
if (BusLogic_ProbeOptions.NoProbe)
return -ENODEV;
BusLogic_ProbeInfoList = (struct BusLogic_ProbeInfo *)
kmalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_ATOMIC);
BusLogic_ProbeInfoList =
kzalloc(BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo), GFP_KERNEL);
if (BusLogic_ProbeInfoList == NULL) {
BusLogic_Error("BusLogic: Unable to allocate Probe Info List\n", NULL);
return -ENOMEM;
}
memset(BusLogic_ProbeInfoList, 0, BusLogic_MaxHostAdapters * sizeof(struct BusLogic_ProbeInfo));
PrototypeHostAdapter = (struct BusLogic_HostAdapter *)
kmalloc(sizeof(struct BusLogic_HostAdapter), GFP_ATOMIC);
PrototypeHostAdapter =
kzalloc(sizeof(struct BusLogic_HostAdapter), GFP_KERNEL);
if (PrototypeHostAdapter == NULL) {
kfree(BusLogic_ProbeInfoList);
BusLogic_Error("BusLogic: Unable to allocate Prototype " "Host Adapter\n", NULL);
return -ENOMEM;
}
memset(PrototypeHostAdapter, 0, sizeof(struct BusLogic_HostAdapter));
#ifdef MODULE
if (BusLogic != NULL)
BusLogic_Setup(BusLogic);
......
......@@ -29,6 +29,13 @@ config SCSI
However, do not compile this as a module if your root file system
(the one containing the directory /) is located on a SCSI device.
config SCSI_TGT
tristate "SCSI target support"
depends on SCSI && EXPERIMENTAL
---help---
If you want to use SCSI target mode drivers enable this option.
If you choose M, the module will be called scsi_tgt.
config SCSI_NETLINK
bool
default n
......@@ -216,6 +223,23 @@ config SCSI_LOGGING
there should be no noticeable performance impact as long as you have
logging turned off.
config SCSI_SCAN_ASYNC
bool "Asynchronous SCSI scanning"
depends on SCSI
help
The SCSI subsystem can probe for devices while the rest of the
system continues booting, and even probe devices on different
busses in parallel, leading to a significant speed-up.
If you have built SCSI as modules, enabling this option can
be a problem as the devices may not have been found by the
time your system expects them to have been. You can load the
scsi_wait_scan module to ensure that all scans have completed.
If you build your SCSI drivers into the kernel, then everything
will work fine if you say Y here.
You can override this choice by specifying scsi_mod.scan="sync"
or "async" on the kernel's command line.
menu "SCSI Transports"
depends on SCSI
......@@ -797,6 +821,20 @@ config SCSI_IBMVSCSI
To compile this driver as a module, choose M here: the
module will be called ibmvscsic.
config SCSI_IBMVSCSIS
tristate "IBM Virtual SCSI Server support"
depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP
help
This is the SRP target driver for IBM pSeries virtual environments.
The userspace component needed to initialize the driver and
documentation can be found:
http://stgt.berlios.de/
To compile this driver as a module, choose M here: the
module will be called ibmvstgt.
config SCSI_INITIO
tristate "Initio 9100U(W) support"
depends on PCI && SCSI
......@@ -944,8 +982,13 @@ config SCSI_STEX
tristate "Promise SuperTrak EX Series support"
depends on PCI && SCSI
---help---
This driver supports Promise SuperTrak EX8350/8300/16350/16300
Storage controllers.
This driver supports Promise SuperTrak EX series storage controllers.
Promise provides Linux RAID configuration utility for these
controllers. Please visit <http://www.promise.com> to download.
To compile this driver as a module, choose M here: the
module will be called stex.
config SCSI_SYM53C8XX_2
tristate "SYM53C8XX Version 2 SCSI support"
......@@ -1026,6 +1069,7 @@ config SCSI_IPR
config SCSI_IPR_TRACE
bool "enable driver internal trace"
depends on SCSI_IPR
default y
help
If you say Y here, the driver will trace all commands issued
to the adapter. Performance impact is minimal. Trace can be
......@@ -1034,6 +1078,7 @@ config SCSI_IPR_TRACE
config SCSI_IPR_DUMP
bool "enable adapter dump support"
depends on SCSI_IPR
default y
help
If you say Y here, the driver will support adapter crash dump.
If you enable this support, the iprdump daemon can be used
......@@ -1734,6 +1779,16 @@ config ZFCP
called zfcp. If you want to compile it as a module, say M here
and read <file:Documentation/modules.txt>.
config SCSI_SRP
tristate "SCSI RDMA Protocol helper library"
depends on SCSI && PCI
select SCSI_TGT
help
If you wish to use SRP target drivers, say Y.
To compile this driver as a module, choose M here: the
module will be called libsrp.
endmenu
source "drivers/scsi/pcmcia/Kconfig"
......
......@@ -21,6 +21,7 @@ CFLAGS_seagate.o = -DARBITRATE -DPARITY -DSEAGATE_USE_ASM
subdir-$(CONFIG_PCMCIA) += pcmcia
obj-$(CONFIG_SCSI) += scsi_mod.o
obj-$(CONFIG_SCSI_TGT) += scsi_tgt.o
obj-$(CONFIG_RAID_ATTRS) += raid_class.o
......@@ -125,7 +126,9 @@ obj-$(CONFIG_SCSI_FCAL) += fcal.o
obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o
obj-$(CONFIG_SCSI_NSP32) += nsp32.o
obj-$(CONFIG_SCSI_IPR) += ipr.o
obj-$(CONFIG_SCSI_SRP) += libsrp.o
obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/
obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/
obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o
obj-$(CONFIG_SCSI_STEX) += stex.o
......@@ -141,6 +144,8 @@ obj-$(CONFIG_CHR_DEV_SCH) += ch.o
# This goes last, so that "real" scsi devices probe earlier
obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o
obj-$(CONFIG_SCSI) += scsi_wait_scan.o
scsi_mod-y += scsi.o hosts.o scsi_ioctl.o constants.o \
scsicam.o scsi_error.o scsi_lib.o \
scsi_scan.o scsi_sysfs.o \
......@@ -149,6 +154,8 @@ scsi_mod-$(CONFIG_SCSI_NETLINK) += scsi_netlink.o
scsi_mod-$(CONFIG_SYSCTL) += scsi_sysctl.o
scsi_mod-$(CONFIG_SCSI_PROC_FS) += scsi_proc.o
scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o
sd_mod-objs := sd.o
sr_mod-objs := sr.o sr_ioctl.o sr_vendor.o
ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
......
......@@ -220,9 +220,11 @@ static void *addresses[] = {
static unsigned short ports[] = { 0x230, 0x330, 0x280, 0x290, 0x330, 0x340, 0x300, 0x310, 0x348, 0x350 };
#define PORT_COUNT ARRAY_SIZE(ports)
#ifndef MODULE
/* possible interrupt channels */
static unsigned short intrs[] = { 10, 11, 12, 15 };
#define INTR_COUNT ARRAY_SIZE(intrs)
#endif /* !MODULE */
/* signatures for NCR 53c406a based controllers */
#if USE_BIOS
......@@ -605,6 +607,7 @@ static int NCR53c406a_release(struct Scsi_Host *shost)
return 0;
}
#ifndef MODULE
/* called from init/main.c */
static int __init NCR53c406a_setup(char *str)
{
......@@ -661,6 +664,8 @@ static int __init NCR53c406a_setup(char *str)
__setup("ncr53c406a=", NCR53c406a_setup);
#endif /* !MODULE */
static const char *NCR53c406a_info(struct Scsi_Host *SChost)
{
DEB(printk("NCR53c406a_info called\n"));
......
......@@ -11,8 +11,8 @@
*----------------------------------------------------------------------------*/
#ifndef AAC_DRIVER_BUILD
# define AAC_DRIVER_BUILD 2409
# define AAC_DRIVER_BRANCH "-mh2"
# define AAC_DRIVER_BUILD 2423
# define AAC_DRIVER_BRANCH "-mh3"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
......
......@@ -518,6 +518,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
*/
unsigned long count = 36000000L; /* 3 minutes */
while (down_trylock(&fibptr->event_wait)) {
int blink;
if (--count == 0) {
spin_lock_irqsave(q->lock, qflags);
q->numpending--;
......@@ -530,6 +531,14 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
}
return -ETIMEDOUT;
}
if ((blink = aac_adapter_check_health(dev)) > 0) {
if (wait == -1) {
printk(KERN_ERR "aacraid: aac_fib_send: adapter blinkLED 0x%x.\n"
"Usually a result of a serious unrecoverable hardware problem\n",
blink);
}
return -EFAULT;
}
udelay(5);
}
} else if (down_interruptible(&fibptr->event_wait)) {
......@@ -1093,6 +1102,20 @@ static int _aac_reset_adapter(struct aac_dev *aac)
goto out;
}
/*
* Loop through the fibs, close the synchronous FIBS
*/
for (index = 0; index < (aac->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB); index++) {
struct fib *fib = &aac->fibs[index];
if (!(fib->hw_fib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) &&
(fib->hw_fib->header.XferState & cpu_to_le32(ResponseExpected))) {
unsigned long flagv;
spin_lock_irqsave(&fib->event_lock, flagv);
up(&fib->event_wait);
spin_unlock_irqrestore(&fib->event_lock, flagv);
schedule();
}
}
index = aac->cardtype;
/*
......
......@@ -586,7 +586,7 @@ static struct scsi_host_template aha1740_template = {
static int aha1740_probe (struct device *dev)
{
int slotbase;
int slotbase, rc;
unsigned int irq_level, irq_type, translation;
struct Scsi_Host *shpnt;
struct aha1740_hostdata *host;
......@@ -641,10 +641,16 @@ static int aha1740_probe (struct device *dev)
}
eisa_set_drvdata (edev, shpnt);
scsi_add_host (shpnt, dev); /* XXX handle failure */
rc = scsi_add_host (shpnt, dev);
if (rc)
goto err_irq;
scsi_scan_host (shpnt);
return 0;
err_irq:
free_irq(irq_level, shpnt);
err_unmap:
dma_unmap_single (&edev->dev, host->ecb_dma_addr,
sizeof (host->ecb), DMA_BIDIRECTIONAL);
......
......@@ -62,6 +62,7 @@ static struct pci_device_id ahd_linux_pci_id_table[] = {
/* aic7901 based controllers */
ID(ID_AHA_29320A),
ID(ID_AHA_29320ALP),
ID(ID_AHA_29320LPE),
/* aic7902 based controllers */
ID(ID_AHA_29320),
ID(ID_AHA_29320B),
......
......@@ -109,7 +109,13 @@ static struct ahd_pci_identity ahd_pci_ident_table [] =
{
ID_AHA_29320ALP,
ID_ALL_MASK,
"Adaptec 29320ALP Ultra320 SCSI adapter",
"Adaptec 29320ALP PCIx Ultra320 SCSI adapter",
ahd_aic7901_setup
},
{
ID_AHA_29320LPE,
ID_ALL_MASK,
"Adaptec 29320LPE PCIe Ultra320 SCSI adapter",
ahd_aic7901_setup
},
/* aic7901A based controllers */
......
......@@ -51,6 +51,7 @@
#define ID_AIC7901 0x800F9005FFFF9005ull
#define ID_AHA_29320A 0x8000900500609005ull
#define ID_AHA_29320ALP 0x8017900500449005ull
#define ID_AHA_29320LPE 0x8017900500459005ull
#define ID_AIC7901A 0x801E9005FFFF9005ull
#define ID_AHA_29320LP 0x8014900500449005ull
......
......@@ -724,6 +724,15 @@ static void asd_free_queues(struct asd_ha_struct *asd_ha)
list_for_each_safe(pos, n, &pending) {
struct asd_ascb *ascb = list_entry(pos, struct asd_ascb, list);
/*
* Delete unexpired ascb timers. This may happen if we issue
* a CONTROL PHY scb to an adapter and rmmod before the scb
* times out. Apparently we don't wait for the CONTROL PHY
* to complete, so it doesn't matter if we kill the timer.
*/
del_timer_sync(&ascb->timer);
WARN_ON(ascb->scb->header.opcode != CONTROL_PHY);
list_del_init(pos);
ASD_DPRINTK("freeing from pending\n");
asd_ascb_free(ascb);
......
......@@ -25,6 +25,7 @@
*/
#include <linux/pci.h>
#include <scsi/scsi_host.h>
#include "aic94xx.h"
#include "aic94xx_reg.h"
......@@ -412,6 +413,39 @@ void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id)
}
}
/* hard reset a phy later */
static void do_phy_reset_later(void *data)
{
struct sas_phy *sas_phy = data;
int error;
ASD_DPRINTK("%s: About to hard reset phy %d\n", __FUNCTION__,
sas_phy->identify.phy_identifier);
/* Reset device port */
error = sas_phy_reset(sas_phy, 1);
if (error)
ASD_DPRINTK("%s: Hard reset of phy %d failed (%d).\n",
__FUNCTION__, sas_phy->identify.phy_identifier, error);
}
static void phy_reset_later(struct sas_phy *sas_phy, struct Scsi_Host *shost)
{
INIT_WORK(&sas_phy->reset_work, do_phy_reset_later, sas_phy);
queue_work(shost->work_q, &sas_phy->reset_work);
}
/* start up the ABORT TASK tmf... */
static void task_kill_later(struct asd_ascb *ascb)
{
struct asd_ha_struct *asd_ha = ascb->ha;
struct sas_ha_struct *sas_ha = &asd_ha->sas_ha;
struct Scsi_Host *shost = sas_ha->core.shost;
struct sas_task *task = ascb->uldd_task;
INIT_WORK(&task->abort_work, (void (*)(void *))sas_task_abort, task);
queue_work(shost->work_q, &task->abort_work);
}
static void escb_tasklet_complete(struct asd_ascb *ascb,
struct done_list_struct *dl)
{
......@@ -439,6 +473,74 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
ascb->scb->header.opcode);
}
/* Catch these before we mask off the sb_opcode bits */
switch (sb_opcode) {
case REQ_TASK_ABORT: {
struct asd_ascb *a, *b;
u16 tc_abort;
tc_abort = *((u16*)(&dl->status_block[1]));
tc_abort = le16_to_cpu(tc_abort);
ASD_DPRINTK("%s: REQ_TASK_ABORT, reason=0x%X\n",
__FUNCTION__, dl->status_block[3]);
/* Find the pending task and abort it. */
list_for_each_entry_safe(a, b, &asd_ha->seq.pend_q, list)
if (a->tc_index == tc_abort) {
task_kill_later(a);
break;
}
goto out;
}
case REQ_DEVICE_RESET: {
struct Scsi_Host *shost = sas_ha->core.shost;
struct sas_phy *dev_phy;
struct asd_ascb *a;
u16 conn_handle;
conn_handle = *((u16*)(&dl->status_block[1]));
conn_handle = le16_to_cpu(conn_handle);
ASD_DPRINTK("%s: REQ_DEVICE_RESET, reason=0x%X\n", __FUNCTION__,
dl->status_block[3]);
/* Kill all pending tasks and reset the device */
dev_phy = NULL;
list_for_each_entry(a, &asd_ha->seq.pend_q, list) {
struct sas_task *task;
struct domain_device *dev;
u16 x;
task = a->uldd_task;
if (!task)
continue;
dev = task->dev;
x = (unsigned long)dev->lldd_dev;
if (x == conn_handle) {
dev_phy = dev->port->phy;
task_kill_later(a);
}
}
/* Reset device port */
if (!dev_phy) {
ASD_DPRINTK("%s: No pending commands; can't reset.\n",
__FUNCTION__);
goto out;
}
phy_reset_later(dev_phy, shost);
goto out;
}
case SIGNAL_NCQ_ERROR:
ASD_DPRINTK("%s: SIGNAL_NCQ_ERROR\n", __FUNCTION__);
goto out;
case CLEAR_NCQ_ERROR:
ASD_DPRINTK("%s: CLEAR_NCQ_ERROR\n", __FUNCTION__);
goto out;
}
sb_opcode &= ~DL_PHY_MASK;
switch (sb_opcode) {
......@@ -469,22 +571,6 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
asd_deform_port(asd_ha, phy);
sas_ha->notify_port_event(sas_phy, PORTE_TIMER_EVENT);
break;
case REQ_TASK_ABORT:
ASD_DPRINTK("%s: phy%d: REQ_TASK_ABORT\n", __FUNCTION__,
phy_id);
break;
case REQ_DEVICE_RESET:
ASD_DPRINTK("%s: phy%d: REQ_DEVICE_RESET\n", __FUNCTION__,
phy_id);
break;
case SIGNAL_NCQ_ERROR:
ASD_DPRINTK("%s: phy%d: SIGNAL_NCQ_ERROR\n", __FUNCTION__,
phy_id);
break;
case CLEAR_NCQ_ERROR:
ASD_DPRINTK("%s: phy%d: CLEAR_NCQ_ERROR\n", __FUNCTION__,
phy_id);
break;
default:
ASD_DPRINTK("%s: phy%d: unknown event:0x%x\n", __FUNCTION__,
phy_id, sb_opcode);
......@@ -504,7 +590,7 @@ static void escb_tasklet_complete(struct asd_ascb *ascb,
break;
}
out:
asd_invalidate_edb(ascb, edb);
}
......
......@@ -294,6 +294,7 @@ static struct Scsi_Host *hosts[FD_MAX_HOSTS + 1] = { NULL };
static int user_fifo_count = 0;
static int user_fifo_size = 0;
#ifndef MODULE
static int __init fd_mcs_setup(char *str)
{
static int done_setup = 0;
......@@ -311,6 +312,7 @@ static int __init fd_mcs_setup(char *str)
}
__setup("fd_mcs=", fd_mcs_setup);
#endif /* !MODULE */
static void print_banner(struct Scsi_Host *shpnt)
{
......
......@@ -263,6 +263,10 @@ static void scsi_host_dev_release(struct device *dev)
kthread_stop(shost->ehandler);
if (shost->work_q)
destroy_workqueue(shost->work_q);
if (shost->uspace_req_q) {
kfree(shost->uspace_req_q->queuedata);
scsi_free_queue(shost->uspace_req_q);
}
scsi_destroy_command_freelist(shost);
if (shost->bqt)
......@@ -301,8 +305,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
if (!shost)
return NULL;
spin_lock_init(&shost->default_lock);
scsi_assign_lock(shost, &shost->default_lock);
shost->host_lock = &shost->default_lock;
spin_lock_init(shost->host_lock);
shost->shost_state = SHOST_CREATED;
INIT_LIST_HEAD(&shost->__devices);
INIT_LIST_HEAD(&shost->__targets);
......
......@@ -3,3 +3,5 @@ obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsic.o
ibmvscsic-y += ibmvscsi.o
ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o
ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o
obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o
此差异已折叠。
......@@ -170,7 +170,7 @@ static int setup_debug = 0;
static void i91uSCBPost(BYTE * pHcb, BYTE * pScb);
/* PCI Devices supported by this driver */
static struct pci_device_id i91u_pci_devices[] __devinitdata = {
static struct pci_device_id i91u_pci_devices[] = {
{ PCI_VENDOR_ID_INIT, I950_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_INIT, I940_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_VENDOR_ID_INIT, I935_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
......
......@@ -79,7 +79,6 @@
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_transport.h>
#include "ipr.h"
/*
......@@ -98,7 +97,7 @@ static DEFINE_SPINLOCK(ipr_driver_lock);
/* This table describes the differences between DMA controller chips */
static const struct ipr_chip_cfg_t ipr_chip_cfg[] = {
{ /* Gemstone, Citrine, and Obsidian */
{ /* Gemstone, Citrine, Obsidian, and Obsidian-E */
.mailbox = 0x0042C,
.cache_line_size = 0x20,
{
......@@ -135,6 +134,7 @@ static const struct ipr_chip_t ipr_chip[] = {
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, &ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] }
};
......@@ -1249,19 +1249,23 @@ static void ipr_log_array_error(struct ipr_ioa_cfg *ioa_cfg,
/**
* ipr_log_hex_data - Log additional hex IOA error data.
* @ioa_cfg: ioa config struct
* @data: IOA error data
* @len: data length
*
* Return value:
* none
**/
static void ipr_log_hex_data(u32 *data, int len)
static void ipr_log_hex_data(struct ipr_ioa_cfg *ioa_cfg, u32 *data, int len)
{
int i;
if (len == 0)
return;
if (ioa_cfg->log_level <= IPR_DEFAULT_LOG_LEVEL)
len = min_t(int, len, IPR_DEFAULT_MAX_ERROR_DUMP);
for (i = 0; i < len / 4; i += 4) {
ipr_err("%08X: %08X %08X %08X %08X\n", i*4,
be32_to_cpu(data[i]),
......@@ -1290,7 +1294,7 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err("%s\n", error->failure_reason);
ipr_err("Remote Adapter VPD:\n");
ipr_log_ext_vpd(&error->vpd);
ipr_log_hex_data(error->data,
ipr_log_hex_data(ioa_cfg, error->data,
be32_to_cpu(hostrcb->hcam.length) -
(offsetof(struct ipr_hostrcb_error, u) +
offsetof(struct ipr_hostrcb_type_17_error, data)));
......@@ -1315,12 +1319,225 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
ipr_err("%s\n", error->failure_reason);
ipr_err("Remote Adapter VPD:\n");
ipr_log_vpd(&error->vpd);
ipr_log_hex_data(error->data,
ipr_log_hex_data(ioa_cfg, error->data,
be32_to_cpu(hostrcb->hcam.length) -
(offsetof(struct ipr_hostrcb_error, u) +
offsetof(struct ipr_hostrcb_type_07_error, data)));
}
static const struct {
u8 active;
char *desc;
} path_active_desc[] = {
{ IPR_PATH_NO_INFO, "Path" },
{ IPR_PATH_ACTIVE, "Active path" },
{ IPR_PATH_NOT_ACTIVE, "Inactive path" }
};
static const struct {
u8 state;
char *desc;
} path_state_desc[] = {
{ IPR_PATH_STATE_NO_INFO, "has no path state information available" },
{ IPR_PATH_HEALTHY, "is healthy" },
{ IPR_PATH_DEGRADED, "is degraded" },
{ IPR_PATH_FAILED, "is failed" }
};
/**
* ipr_log_fabric_path - Log a fabric path error
* @hostrcb: hostrcb struct
* @fabric: fabric descriptor
*
* Return value:
* none
**/
static void ipr_log_fabric_path(struct ipr_hostrcb *hostrcb,
struct ipr_hostrcb_fabric_desc *fabric)
{
int i, j;
u8 path_state = fabric->path_state;
u8 active = path_state & IPR_PATH_ACTIVE_MASK;
u8 state = path_state & IPR_PATH_STATE_MASK;
for (i = 0; i < ARRAY_SIZE(path_active_desc); i++) {
if (path_active_desc[i].active != active)
continue;
for (j = 0; j < ARRAY_SIZE(path_state_desc); j++) {
if (path_state_desc[j].state != state)
continue;
if (fabric->cascaded_expander == 0xff && fabric->phy == 0xff) {
ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d\n",
path_active_desc[i].desc, path_state_desc[j].desc,
fabric->ioa_port);
} else if (fabric->cascaded_expander == 0xff) {
ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Phy=%d\n",
path_active_desc[i].desc, path_state_desc[j].desc,
fabric->ioa_port, fabric->phy);
} else if (fabric->phy == 0xff) {
ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d\n",
path_active_desc[i].desc, path_state_desc[j].desc,
fabric->ioa_port, fabric->cascaded_expander);
} else {
ipr_hcam_err(hostrcb, "%s %s: IOA Port=%d, Cascade=%d, Phy=%d\n",
path_active_desc[i].desc, path_state_desc[j].desc,
fabric->ioa_port, fabric->cascaded_expander, fabric->phy);
}
return;
}
}
ipr_err("Path state=%02X IOA Port=%d Cascade=%d Phy=%d\n", path_state,
fabric->ioa_port, fabric->cascaded_expander, fabric->phy);
}
static const struct {
u8 type;
char *desc;
} path_type_desc[] = {
{ IPR_PATH_CFG_IOA_PORT, "IOA port" },
{ IPR_PATH_CFG_EXP_PORT, "Expander port" },
{ IPR_PATH_CFG_DEVICE_PORT, "Device port" },
{ IPR_PATH_CFG_DEVICE_LUN, "Device LUN" }
};
static const struct {
u8 status;
char *desc;
} path_status_desc[] = {
{ IPR_PATH_CFG_NO_PROB, "Functional" },
{ IPR_PATH_CFG_DEGRADED, "Degraded" },
{ IPR_PATH_CFG_FAILED, "Failed" },
{ IPR_PATH_CFG_SUSPECT, "Suspect" },
{ IPR_PATH_NOT_DETECTED, "Missing" },
{ IPR_PATH_INCORRECT_CONN, "Incorrectly connected" }
};
static const char *link_rate[] = {
"unknown",
"disabled",
"phy reset problem",
"spinup hold",
"port selector",
"unknown",
"unknown",
"unknown",
"1.5Gbps",
"3.0Gbps",
"unknown",
"unknown",
"unknown",
"unknown",
"unknown",
"unknown"
};
/**
* ipr_log_path_elem - Log a fabric path element.
* @hostrcb: hostrcb struct
* @cfg: fabric path element struct
*
* Return value:
* none
**/
static void ipr_log_path_elem(struct ipr_hostrcb *hostrcb,
struct ipr_hostrcb_config_element *cfg)
{
int i, j;
u8 type = cfg->type_status & IPR_PATH_CFG_TYPE_MASK;
u8 status = cfg->type_status & IPR_PATH_CFG_STATUS_MASK;
if (type == IPR_PATH_CFG_NOT_EXIST)
return;
for (i = 0; i < ARRAY_SIZE(path_type_desc); i++) {
if (path_type_desc[i].type != type)
continue;
for (j = 0; j < ARRAY_SIZE(path_status_desc); j++) {
if (path_status_desc[j].status != status)
continue;
if (type == IPR_PATH_CFG_IOA_PORT) {
ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, WWN=%08X%08X\n",
path_status_desc[j].desc, path_type_desc[i].desc,
cfg->phy, link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
} else {
if (cfg->cascaded_expander == 0xff && cfg->phy == 0xff) {
ipr_hcam_err(hostrcb, "%s %s: Link rate=%s, WWN=%08X%08X\n",
path_status_desc[j].desc, path_type_desc[i].desc,
link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
} else if (cfg->cascaded_expander == 0xff) {
ipr_hcam_err(hostrcb, "%s %s: Phy=%d, Link rate=%s, "
"WWN=%08X%08X\n", path_status_desc[j].desc,
path_type_desc[i].desc, cfg->phy,
link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
} else if (cfg->phy == 0xff) {
ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Link rate=%s, "
"WWN=%08X%08X\n", path_status_desc[j].desc,
path_type_desc[i].desc, cfg->cascaded_expander,
link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
} else {
ipr_hcam_err(hostrcb, "%s %s: Cascade=%d, Phy=%d, Link rate=%s "
"WWN=%08X%08X\n", path_status_desc[j].desc,
path_type_desc[i].desc, cfg->cascaded_expander, cfg->phy,
link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
}
}
return;
}
}
ipr_hcam_err(hostrcb, "Path element=%02X: Cascade=%d Phy=%d Link rate=%s "
"WWN=%08X%08X\n", cfg->type_status, cfg->cascaded_expander, cfg->phy,
link_rate[cfg->link_rate & IPR_PHY_LINK_RATE_MASK],
be32_to_cpu(cfg->wwid[0]), be32_to_cpu(cfg->wwid[1]));
}
/**
* ipr_log_fabric_error - Log a fabric error.
* @ioa_cfg: ioa config struct
* @hostrcb: hostrcb struct
*
* Return value:
* none
**/
static void ipr_log_fabric_error(struct ipr_ioa_cfg *ioa_cfg,
struct ipr_hostrcb *hostrcb)
{
struct ipr_hostrcb_type_20_error *error;
struct ipr_hostrcb_fabric_desc *fabric;
struct ipr_hostrcb_config_element *cfg;
int i, add_len;
error = &hostrcb->hcam.u.error.u.type_20_error;
error->failure_reason[sizeof(error->failure_reason) - 1] = '\0';
ipr_hcam_err(hostrcb, "%s\n", error->failure_reason);
add_len = be32_to_cpu(hostrcb->hcam.length) -
(offsetof(struct ipr_hostrcb_error, u) +
offsetof(struct ipr_hostrcb_type_20_error, desc));
for (i = 0, fabric = error->desc; i < error->num_entries; i++) {
ipr_log_fabric_path(hostrcb, fabric);
for_each_fabric_cfg(fabric, cfg)
ipr_log_path_elem(hostrcb, cfg);
add_len -= be16_to_cpu(fabric->length);
fabric = (struct ipr_hostrcb_fabric_desc *)
((unsigned long)fabric + be16_to_cpu(fabric->length));
}
ipr_log_hex_data(ioa_cfg, (u32 *)fabric, add_len);
}
/**
* ipr_log_generic_error - Log an adapter error.
* @ioa_cfg: ioa config struct
......@@ -1332,7 +1549,7 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
static void ipr_log_generic_error(struct ipr_ioa_cfg *ioa_cfg,
struct ipr_hostrcb *hostrcb)
{
ipr_log_hex_data(hostrcb->hcam.u.raw.data,
ipr_log_hex_data(ioa_cfg, hostrcb->hcam.u.raw.data,
be32_to_cpu(hostrcb->hcam.length));
}
......@@ -1394,13 +1611,7 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
if (!ipr_error_table[error_index].log_hcam)
return;
if (ipr_is_device(&hostrcb->hcam.u.error.failing_dev_res_addr)) {
ipr_ra_err(ioa_cfg, hostrcb->hcam.u.error.failing_dev_res_addr,
"%s\n", ipr_error_table[error_index].error);
} else {
dev_err(&ioa_cfg->pdev->dev, "%s\n",
ipr_error_table[error_index].error);
}
ipr_hcam_err(hostrcb, "%s\n", ipr_error_table[error_index].error);
/* Set indication we have logged an error */
ioa_cfg->errors_logged++;
......@@ -1437,6 +1648,9 @@ static void ipr_handle_log_data(struct ipr_ioa_cfg *ioa_cfg,
case IPR_HOST_RCB_OVERLAY_ID_17:
ipr_log_enhanced_dual_ioa_error(ioa_cfg, hostrcb);
break;
case IPR_HOST_RCB_OVERLAY_ID_20:
ipr_log_fabric_error(ioa_cfg, hostrcb);
break;
case IPR_HOST_RCB_OVERLAY_ID_1:
case IPR_HOST_RCB_OVERLAY_ID_DEFAULT:
default:
......@@ -2970,7 +3184,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
struct ipr_dump *dump;
unsigned long lock_flags = 0;
ENTER;
dump = kzalloc(sizeof(struct ipr_dump), GFP_KERNEL);
if (!dump) {
......@@ -2997,7 +3210,6 @@ static int ipr_alloc_dump(struct ipr_ioa_cfg *ioa_cfg)
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
LEAVE;
return 0;
}
......@@ -3574,6 +3786,12 @@ static int ipr_sata_reset(struct ata_port *ap, unsigned int *classes)
ENTER;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
while(ioa_cfg->in_reset_reload) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
}
res = sata_port->res;
if (res) {
rc = ipr_device_reset(ioa_cfg, res);
......@@ -3637,6 +3855,10 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd * scsi_cmd)
if (ipr_cmd->ioarcb.res_handle == res->cfgte.res_handle) {
if (ipr_cmd->scsi_cmd)
ipr_cmd->done = ipr_scsi_eh_done;
if (ipr_cmd->qc && !(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) {
ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
}
}
}
......@@ -3771,7 +3993,7 @@ static int ipr_cancel_op(struct scsi_cmnd * scsi_cmd)
*/
if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead)
return FAILED;
if (!res || (!ipr_is_gscsi(res) && !ipr_is_vset_device(res)))
if (!res || !ipr_is_gscsi(res))
return FAILED;
list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
......@@ -4616,7 +4838,7 @@ static int ipr_queuecommand(struct scsi_cmnd *scsi_cmd,
* Return value:
* 0 on success / other on failure
**/
int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
static int ipr_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
{
struct ipr_resource_entry *res;
......@@ -4649,40 +4871,6 @@ static const char * ipr_ioa_info(struct Scsi_Host *host)
return buffer;
}
/**
* ipr_scsi_timed_out - Handle scsi command timeout
* @scsi_cmd: scsi command struct
*
* Return value:
* EH_NOT_HANDLED
**/
enum scsi_eh_timer_return ipr_scsi_timed_out(struct scsi_cmnd *scsi_cmd)
{
struct ipr_ioa_cfg *ioa_cfg;
struct ipr_cmnd *ipr_cmd;
unsigned long flags;
ENTER;
spin_lock_irqsave(scsi_cmd->device->host->host_lock, flags);
ioa_cfg = (struct ipr_ioa_cfg *)scsi_cmd->device->host->hostdata;
list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
if (ipr_cmd->qc && ipr_cmd->qc->scsicmd == scsi_cmd) {
ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT;
ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED;
break;
}
}
spin_unlock_irqrestore(scsi_cmd->device->host->host_lock, flags);
LEAVE;
return EH_NOT_HANDLED;
}
static struct scsi_transport_template ipr_transport_template = {
.eh_timed_out = ipr_scsi_timed_out
};
static struct scsi_host_template driver_template = {
.module = THIS_MODULE,
.name = "IPR",
......@@ -4777,6 +4965,12 @@ static void ipr_ata_post_internal(struct ata_queued_cmd *qc)
unsigned long flags;
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
while(ioa_cfg->in_reset_reload) {
spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
}
list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) {
if (ipr_cmd->qc == qc) {
ipr_device_reset(ioa_cfg, sata_port->res);
......@@ -6833,6 +7027,7 @@ static int __devinit ipr_alloc_mem(struct ipr_ioa_cfg *ioa_cfg)
ioa_cfg->hostrcb[i]->hostrcb_dma =
ioa_cfg->hostrcb_dma[i] + offsetof(struct ipr_hostrcb, hcam);
ioa_cfg->hostrcb[i]->ioa_cfg = ioa_cfg;
list_add_tail(&ioa_cfg->hostrcb[i]->queue, &ioa_cfg->hostrcb_free_q);
}
......@@ -7018,7 +7213,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
ioa_cfg = (struct ipr_ioa_cfg *)host->hostdata;
memset(ioa_cfg, 0, sizeof(struct ipr_ioa_cfg));
host->transportt = &ipr_transport_template;
ata_host_init(&ioa_cfg->ata_host, &pdev->dev,
sata_port_info.flags, &ipr_sata_ops);
......@@ -7352,12 +7546,24 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B8,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[0] },
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
......@@ -7367,6 +7573,9 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_571F,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572F,
0, 0, (kernel_ulong_t)&ipr_chip_cfg[1] },
{ }
};
MODULE_DEVICE_TABLE(pci, ipr_pci_table);
......
......@@ -37,8 +37,8 @@
/*
* Literals
*/
#define IPR_DRIVER_VERSION "2.2.0"
#define IPR_DRIVER_DATE "(September 25, 2006)"
#define IPR_DRIVER_VERSION "2.3.0"
#define IPR_DRIVER_DATE "(November 8, 2006)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
......@@ -54,6 +54,8 @@
*/
#define IPR_NUM_BASE_CMD_BLKS 100
#define PCI_DEVICE_ID_IBM_OBSIDIAN_E 0x0339
#define IPR_SUBS_DEV_ID_2780 0x0264
#define IPR_SUBS_DEV_ID_5702 0x0266
#define IPR_SUBS_DEV_ID_5703 0x0278
......@@ -66,7 +68,11 @@
#define IPR_SUBS_DEV_ID_571F 0x02D5
#define IPR_SUBS_DEV_ID_572A 0x02C1
#define IPR_SUBS_DEV_ID_572B 0x02C2
#define IPR_SUBS_DEV_ID_572F 0x02C3
#define IPR_SUBS_DEV_ID_575B 0x030D
#define IPR_SUBS_DEV_ID_575C 0x0338
#define IPR_SUBS_DEV_ID_57B7 0x0360
#define IPR_SUBS_DEV_ID_57B8 0x02C2
#define IPR_NAME "ipr"
......@@ -98,6 +104,7 @@
#define IPR_IOASC_IOA_WAS_RESET 0x10000001
#define IPR_IOASC_PCI_ACCESS_ERROR 0x10000002
#define IPR_DEFAULT_MAX_ERROR_DUMP 984
#define IPR_NUM_LOG_HCAMS 2
#define IPR_NUM_CFG_CHG_HCAMS 2
#define IPR_NUM_HCAMS (IPR_NUM_LOG_HCAMS + IPR_NUM_CFG_CHG_HCAMS)
......@@ -731,6 +738,64 @@ struct ipr_hostrcb_type_17_error {
u32 data[476];
}__attribute__((packed, aligned (4)));
struct ipr_hostrcb_config_element {
u8 type_status;
#define IPR_PATH_CFG_TYPE_MASK 0xF0
#define IPR_PATH_CFG_NOT_EXIST 0x00
#define IPR_PATH_CFG_IOA_PORT 0x10
#define IPR_PATH_CFG_EXP_PORT 0x20
#define IPR_PATH_CFG_DEVICE_PORT 0x30
#define IPR_PATH_CFG_DEVICE_LUN 0x40
#define IPR_PATH_CFG_STATUS_MASK 0x0F
#define IPR_PATH_CFG_NO_PROB 0x00
#define IPR_PATH_CFG_DEGRADED 0x01
#define IPR_PATH_CFG_FAILED 0x02
#define IPR_PATH_CFG_SUSPECT 0x03
#define IPR_PATH_NOT_DETECTED 0x04
#define IPR_PATH_INCORRECT_CONN 0x05
u8 cascaded_expander;
u8 phy;
u8 link_rate;
#define IPR_PHY_LINK_RATE_MASK 0x0F
__be32 wwid[2];
}__attribute__((packed, aligned (4)));
struct ipr_hostrcb_fabric_desc {
__be16 length;
u8 ioa_port;
u8 cascaded_expander;
u8 phy;
u8 path_state;
#define IPR_PATH_ACTIVE_MASK 0xC0
#define IPR_PATH_NO_INFO 0x00
#define IPR_PATH_ACTIVE 0x40
#define IPR_PATH_NOT_ACTIVE 0x80
#define IPR_PATH_STATE_MASK 0x0F
#define IPR_PATH_STATE_NO_INFO 0x00
#define IPR_PATH_HEALTHY 0x01
#define IPR_PATH_DEGRADED 0x02
#define IPR_PATH_FAILED 0x03
__be16 num_entries;
struct ipr_hostrcb_config_element elem[1];
}__attribute__((packed, aligned (4)));
#define for_each_fabric_cfg(fabric, cfg) \
for (cfg = (fabric)->elem; \
cfg < ((fabric)->elem + be16_to_cpu((fabric)->num_entries)); \
cfg++)
struct ipr_hostrcb_type_20_error {
u8 failure_reason[64];
u8 reserved[3];
u8 num_entries;
struct ipr_hostrcb_fabric_desc desc[1];
}__attribute__((packed, aligned (4)));
struct ipr_hostrcb_error {
__be32 failing_dev_ioasc;
struct ipr_res_addr failing_dev_res_addr;
......@@ -747,6 +812,7 @@ struct ipr_hostrcb_error {
struct ipr_hostrcb_type_13_error type_13_error;
struct ipr_hostrcb_type_14_error type_14_error;
struct ipr_hostrcb_type_17_error type_17_error;
struct ipr_hostrcb_type_20_error type_20_error;
} u;
}__attribute__((packed, aligned (4)));
......@@ -786,6 +852,7 @@ struct ipr_hcam {
#define IPR_HOST_RCB_OVERLAY_ID_14 0x14
#define IPR_HOST_RCB_OVERLAY_ID_16 0x16
#define IPR_HOST_RCB_OVERLAY_ID_17 0x17
#define IPR_HOST_RCB_OVERLAY_ID_20 0x20
#define IPR_HOST_RCB_OVERLAY_ID_DEFAULT 0xFF
u8 reserved1[3];
......@@ -805,6 +872,7 @@ struct ipr_hostrcb {
struct ipr_hcam hcam;
dma_addr_t hostrcb_dma;
struct list_head queue;
struct ipr_ioa_cfg *ioa_cfg;
};
/* IPR smart dump table structures */
......@@ -1283,6 +1351,17 @@ struct ipr_ucode_image_header {
} \
}
#define ipr_hcam_err(hostrcb, fmt, ...) \
{ \
if (ipr_is_device(&(hostrcb)->hcam.u.error.failing_dev_res_addr)) { \
ipr_ra_err((hostrcb)->ioa_cfg, \
(hostrcb)->hcam.u.error.failing_dev_res_addr, \
fmt, ##__VA_ARGS__); \
} else { \
dev_err(&(hostrcb)->ioa_cfg->pdev->dev, fmt, ##__VA_ARGS__); \
} \
}
#define ipr_trace ipr_dbg("%s: %s: Line: %d\n",\
__FILE__, __FUNCTION__, __LINE__)
......
......@@ -5001,7 +5001,7 @@ ips_init_copperhead(ips_ha_t * ha)
break;
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
}
if (j >= 45)
......@@ -5027,7 +5027,7 @@ ips_init_copperhead(ips_ha_t * ha)
break;
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
}
if (j >= 240)
......@@ -5045,7 +5045,7 @@ ips_init_copperhead(ips_ha_t * ha)
break;
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
}
if (i >= 240)
......@@ -5095,7 +5095,7 @@ ips_init_copperhead_memio(ips_ha_t * ha)
break;
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
}
if (j >= 45)
......@@ -5121,7 +5121,7 @@ ips_init_copperhead_memio(ips_ha_t * ha)
break;
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
}
if (j >= 240)
......@@ -5139,7 +5139,7 @@ ips_init_copperhead_memio(ips_ha_t * ha)
break;
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
}
if (i >= 240)
......@@ -5191,7 +5191,7 @@ ips_init_morpheus(ips_ha_t * ha)
break;
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
}
if (i >= 45) {
......@@ -5217,7 +5217,7 @@ ips_init_morpheus(ips_ha_t * ha)
if (Post != 0x4F00)
break;
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
}
if (i >= 120) {
......@@ -5247,7 +5247,7 @@ ips_init_morpheus(ips_ha_t * ha)
break;
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
}
if (i >= 240) {
......@@ -5307,12 +5307,12 @@ ips_reset_copperhead(ips_ha_t * ha)
outb(IPS_BIT_RST, ha->io_addr + IPS_REG_SCPR);
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
outb(0, ha->io_addr + IPS_REG_SCPR);
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
if ((*ha->func.init) (ha))
break;
......@@ -5352,12 +5352,12 @@ ips_reset_copperhead_memio(ips_ha_t * ha)
writeb(IPS_BIT_RST, ha->mem_ptr + IPS_REG_SCPR);
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
writeb(0, ha->mem_ptr + IPS_REG_SCPR);
/* Delay for 1 Second */
msleep(IPS_ONE_SEC);
MDELAY(IPS_ONE_SEC);
if ((*ha->func.init) (ha))
break;
......@@ -5398,7 +5398,7 @@ ips_reset_morpheus(ips_ha_t * ha)
writel(0x80000000, ha->mem_ptr + IPS_REG_I960_IDR);
/* Delay for 5 Seconds */
msleep(5 * IPS_ONE_SEC);
MDELAY(5 * IPS_ONE_SEC);
/* Do a PCI config read to wait for adapter */
pci_read_config_byte(ha->pcidev, 4, &junk);
......
......@@ -51,6 +51,7 @@
#define _IPS_H_
#include <linux/version.h>
#include <linux/nmi.h>
#include <asm/uaccess.h>
#include <asm/io.h>
......@@ -116,9 +117,11 @@
dev_printk(level , &((pcidev)->dev) , format , ## arg)
#endif
#ifndef MDELAY
#define MDELAY mdelay
#endif
#define MDELAY(n) \
do { \
mdelay(n); \
touch_nmi_watchdog(); \
} while (0)
#ifndef min
#define min(x,y) ((x) < (y) ? x : y)
......
......@@ -597,10 +597,15 @@ static struct domain_device *sas_ex_discover_end_dev(
child->iproto = phy->attached_iproto;
memcpy(child->sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE);
sas_hash_addr(child->hashed_sas_addr, child->sas_addr);
phy->port = sas_port_alloc(&parent->rphy->dev, phy_id);
BUG_ON(!phy->port);
/* FIXME: better error handling*/
BUG_ON(sas_port_add(phy->port) != 0);
if (!phy->port) {
phy->port = sas_port_alloc(&parent->rphy->dev, phy_id);
if (unlikely(!phy->port))
goto out_err;
if (unlikely(sas_port_add(phy->port) != 0)) {
sas_port_free(phy->port);
goto out_err;
}
}
sas_ex_get_linkrate(parent, child, phy);
if ((phy->attached_tproto & SAS_PROTO_STP) || phy->attached_sata_dev) {
......@@ -615,8 +620,7 @@ static struct domain_device *sas_ex_discover_end_dev(
SAS_DPRINTK("report phy sata to %016llx:0x%x returned "
"0x%x\n", SAS_ADDR(parent->sas_addr),
phy_id, res);
kfree(child);
return NULL;
goto out_free;
}
memcpy(child->frame_rcvd, &child->sata_dev.rps_resp.rps.fis,
sizeof(struct dev_to_host_fis));
......@@ -627,14 +631,14 @@ static struct domain_device *sas_ex_discover_end_dev(
"%016llx:0x%x returned 0x%x\n",
SAS_ADDR(child->sas_addr),
SAS_ADDR(parent->sas_addr), phy_id, res);
kfree(child);
return NULL;
goto out_free;
}
} else if (phy->attached_tproto & SAS_PROTO_SSP) {
child->dev_type = SAS_END_DEV;
rphy = sas_end_device_alloc(phy->port);
/* FIXME: error handling */
BUG_ON(!rphy);
if (unlikely(!rphy))
goto out_free;
child->tproto = phy->attached_tproto;
sas_init_dev(child);
......@@ -651,9 +655,7 @@ static struct domain_device *sas_ex_discover_end_dev(
"at %016llx:0x%x returned 0x%x\n",
SAS_ADDR(child->sas_addr),
SAS_ADDR(parent->sas_addr), phy_id, res);
/* FIXME: this kfrees list elements without removing them */
//kfree(child);
return NULL;
goto out_list_del;
}
} else {
SAS_DPRINTK("target proto 0x%x at %016llx:0x%x not handled\n",
......@@ -663,6 +665,16 @@ static struct domain_device *sas_ex_discover_end_dev(
list_add_tail(&child->siblings, &parent_ex->children);
return child;
out_list_del:
list_del(&child->dev_list_node);
sas_rphy_free(rphy);
out_free:
sas_port_delete(phy->port);
out_err:
phy->port = NULL;
kfree(child);
return NULL;
}
static struct domain_device *sas_ex_discover_expander(
......
......@@ -114,6 +114,8 @@ int sas_register_ha(struct sas_ha_struct *sas_ha)
}
}
INIT_LIST_HEAD(&sas_ha->eh_done_q);
return 0;
Undo_ports:
......@@ -144,7 +146,7 @@ static int sas_get_linkerrors(struct sas_phy *phy)
return sas_smp_get_phy_events(phy);
}
static int sas_phy_reset(struct sas_phy *phy, int hard_reset)
int sas_phy_reset(struct sas_phy *phy, int hard_reset)
{
int ret;
enum phy_func reset_type;
......
......@@ -29,9 +29,11 @@
#include <scsi/scsi_device.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_transport.h>
#include <scsi/scsi_transport_sas.h>
#include "../scsi_sas_internal.h"
#include "../scsi_transport_api.h"
#include <linux/err.h>
#include <linux/blkdev.h>
......@@ -46,6 +48,7 @@ static void sas_scsi_task_done(struct sas_task *task)
{
struct task_status_struct *ts = &task->task_status;
struct scsi_cmnd *sc = task->uldd_task;
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(sc->device->host);
unsigned ts_flags = task->task_state_flags;
int hs = 0, stat = 0;
......@@ -116,7 +119,7 @@ static void sas_scsi_task_done(struct sas_task *task)
sas_free_task(task);
/* This is very ugly but this is how SCSI Core works. */
if (ts_flags & SAS_TASK_STATE_ABORTED)
scsi_finish_command(sc);
scsi_eh_finish_cmd(sc, &sas_ha->eh_done_q);
else
sc->scsi_done(sc);
}
......@@ -307,6 +310,15 @@ static enum task_disposition sas_scsi_find_task(struct sas_task *task)
spin_unlock_irqrestore(&core->task_queue_lock, flags);
}
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("%s: task 0x%p already aborted\n",
__FUNCTION__, task);
return TASK_IS_ABORTED;
}
spin_unlock_irqrestore(&task->task_state_lock, flags);
for (i = 0; i < 5; i++) {
SAS_DPRINTK("%s: aborting task 0x%p\n", __FUNCTION__, task);
res = si->dft->lldd_abort_task(task);
......@@ -409,13 +421,16 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
SAS_DPRINTK("going over list...\n");
list_for_each_entry_safe(cmd, n, &error_q, eh_entry) {
struct sas_task *task = TO_SAS_TASK(cmd);
list_del_init(&cmd->eh_entry);
if (!task) {
SAS_DPRINTK("%s: taskless cmd?!\n", __FUNCTION__);
continue;
}
SAS_DPRINTK("trying to find task 0x%p\n", task);
list_del_init(&cmd->eh_entry);
res = sas_scsi_find_task(task);
cmd->eh_eflags = 0;
shost->host_failed--;
switch (res) {
case TASK_IS_DONE:
......@@ -491,6 +506,7 @@ void sas_scsi_recover_host(struct Scsi_Host *shost)
}
}
out:
scsi_eh_flush_done_q(&ha->eh_done_q);
SAS_DPRINTK("--- Exit %s\n", __FUNCTION__);
return;
clear_q:
......@@ -508,12 +524,18 @@ enum scsi_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd)
unsigned long flags;
if (!task) {
SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
SAS_DPRINTK("command 0x%p, task 0x%p, gone: EH_HANDLED\n",
cmd, task);
return EH_HANDLED;
}
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_INITIATOR_ABORTED) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("command 0x%p, task 0x%p, aborted by initiator: "
"EH_NOT_HANDLED\n", cmd, task);
return EH_NOT_HANDLED;
}
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("command 0x%p, task 0x%p, timed out: EH_HANDLED\n",
......@@ -777,6 +799,64 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
spin_unlock_irqrestore(&core->task_queue_lock, flags);
}
static int do_sas_task_abort(struct sas_task *task)
{
struct scsi_cmnd *sc = task->uldd_task;
struct sas_internal *si =
to_sas_internal(task->dev->port->ha->core.shost->transportt);
unsigned long flags;
int res;
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_ABORTED) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
SAS_DPRINTK("%s: Task %p already aborted.\n", __FUNCTION__,
task);
return 0;
}
task->task_state_flags |= SAS_TASK_INITIATOR_ABORTED;
if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
task->task_state_flags |= SAS_TASK_STATE_ABORTED;
spin_unlock_irqrestore(&task->task_state_lock, flags);
if (!si->dft->lldd_abort_task)
return -ENODEV;
res = si->dft->lldd_abort_task(task);
if ((task->task_state_flags & SAS_TASK_STATE_DONE) ||
(res == TMF_RESP_FUNC_COMPLETE))
{
/* SMP commands don't have scsi_cmds(?) */
if (!sc) {
task->task_done(task);
return 0;
}
scsi_req_abort_cmd(sc);
scsi_schedule_eh(sc->device->host);
return 0;
}
spin_lock_irqsave(&task->task_state_lock, flags);
task->task_state_flags &= ~SAS_TASK_INITIATOR_ABORTED;
if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
task->task_state_flags &= ~SAS_TASK_STATE_ABORTED;
spin_unlock_irqrestore(&task->task_state_lock, flags);
return -EAGAIN;
}
void sas_task_abort(struct sas_task *task)
{
int i;
for (i = 0; i < 5; i++)
if (!do_sas_task_abort(task))
return;
SAS_DPRINTK("%s: Could not kill task!\n", __FUNCTION__);
}
EXPORT_SYMBOL_GPL(sas_queuecommand);
EXPORT_SYMBOL_GPL(sas_target_alloc);
EXPORT_SYMBOL_GPL(sas_slave_configure);
......@@ -784,3 +864,5 @@ EXPORT_SYMBOL_GPL(sas_slave_destroy);
EXPORT_SYMBOL_GPL(sas_change_queue_depth);
EXPORT_SYMBOL_GPL(sas_change_queue_type);
EXPORT_SYMBOL_GPL(sas_bios_param);
EXPORT_SYMBOL_GPL(sas_task_abort);
EXPORT_SYMBOL_GPL(sas_phy_reset);
/*
* SCSI RDAM Protocol lib functions
*
* Copyright (C) 2006 FUJITA Tomonori <tomof@acm.org>
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <linux/err.h>
#include <linux/kfifo.h>
#include <linux/scatterlist.h>
#include <linux/dma-mapping.h>
#include <linux/pci.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_tgt.h>
#include <scsi/srp.h>
#include <scsi/libsrp.h>
enum srp_task_attributes {
SRP_SIMPLE_TASK = 0,
SRP_HEAD_TASK = 1,
SRP_ORDERED_TASK = 2,
SRP_ACA_TASK = 4
};
/* tmp - will replace with SCSI logging stuff */
#define eprintk(fmt, args...) \
do { \
printk("%s(%d) " fmt, __FUNCTION__, __LINE__, ##args); \
} while (0)
/* #define dprintk eprintk */
#define dprintk(fmt, args...)
static int srp_iu_pool_alloc(struct srp_queue *q, size_t max,
struct srp_buf **ring)
{
int i;
struct iu_entry *iue;
q->pool = kcalloc(max, sizeof(struct iu_entry *), GFP_KERNEL);
if (!q->pool)
return -ENOMEM;
q->items = kcalloc(max, sizeof(struct iu_entry), GFP_KERNEL);
if (!q->items)
goto free_pool;
spin_lock_init(&q->lock);
q->queue = kfifo_init((void *) q->pool, max * sizeof(void *),
GFP_KERNEL, &q->lock);
if (IS_ERR(q->queue))
goto free_item;
for (i = 0, iue = q->items; i < max; i++) {
__kfifo_put(q->queue, (void *) &iue, sizeof(void *));
iue->sbuf = ring[i];
iue++;
}
return 0;
free_item:
kfree(q->items);
free_pool:
kfree(q->pool);
return -ENOMEM;
}
static void srp_iu_pool_free(struct srp_queue *q)
{
kfree(q->items);
kfree(q->pool);
}
static struct srp_buf **srp_ring_alloc(struct device *dev,
size_t max, size_t size)
{
int i;
struct srp_buf **ring;
ring = kcalloc(max, sizeof(struct srp_buf *), GFP_KERNEL);
if (!ring)
return NULL;
for (i = 0; i < max; i++) {
ring[i] = kzalloc(sizeof(struct srp_buf), GFP_KERNEL);
if (!ring[i])
goto out;
ring[i]->buf = dma_alloc_coherent(dev, size, &ring[i]->dma,
GFP_KERNEL);
if (!ring[i]->buf)
goto out;
}
return ring;
out:
for (i = 0; i < max && ring[i]; i++) {
if (ring[i]->buf)
dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
kfree(ring[i]);
}
kfree(ring);
return NULL;
}
static void srp_ring_free(struct device *dev, struct srp_buf **ring, size_t max,
size_t size)
{
int i;
for (i = 0; i < max; i++) {
dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma);
kfree(ring[i]);
}
}
int srp_target_alloc(struct srp_target *target, struct device *dev,
size_t nr, size_t iu_size)
{
int err;
spin_lock_init(&target->lock);
INIT_LIST_HEAD(&target->cmd_queue);
target->dev = dev;
target->dev->driver_data = target;
target->srp_iu_size = iu_size;
target->rx_ring_size = nr;
target->rx_ring = srp_ring_alloc(target->dev, nr, iu_size);
if (!target->rx_ring)
return -ENOMEM;
err = srp_iu_pool_alloc(&target->iu_queue, nr, target->rx_ring);
if (err)
goto free_ring;
return 0;
free_ring:
srp_ring_free(target->dev, target->rx_ring, nr, iu_size);
return -ENOMEM;
}
EXPORT_SYMBOL_GPL(srp_target_alloc);
void srp_target_free(struct srp_target *target)
{
srp_ring_free(target->dev, target->rx_ring, target->rx_ring_size,
target->srp_iu_size);
srp_iu_pool_free(&target->iu_queue);
}
EXPORT_SYMBOL_GPL(srp_target_free);
struct iu_entry *srp_iu_get(struct srp_target *target)
{
struct iu_entry *iue = NULL;
kfifo_get(target->iu_queue.queue, (void *) &iue, sizeof(void *));
if (!iue)
return iue;
iue->target = target;
INIT_LIST_HEAD(&iue->ilist);
iue->flags = 0;
return iue;
}
EXPORT_SYMBOL_GPL(srp_iu_get);
void srp_iu_put(struct iu_entry *iue)
{
kfifo_put(iue->target->iu_queue.queue, (void *) &iue, sizeof(void *));
}
EXPORT_SYMBOL_GPL(srp_iu_put);
static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md,
enum dma_data_direction dir, srp_rdma_t rdma_io,
int dma_map, int ext_desc)
{
struct iu_entry *iue = NULL;
struct scatterlist *sg = NULL;
int err, nsg = 0, len;
if (dma_map) {
iue = (struct iu_entry *) sc->SCp.ptr;
sg = sc->request_buffer;
dprintk("%p %u %u %d\n", iue, sc->request_bufflen,
md->len, sc->use_sg);
nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg,
DMA_BIDIRECTIONAL);
if (!nsg) {
printk("fail to map %p %d\n", iue, sc->use_sg);
return 0;
}
len = min(sc->request_bufflen, md->len);
} else
len = md->len;
err = rdma_io(sc, sg, nsg, md, 1, dir, len);
if (dma_map)
dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL);
return err;
}
static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
struct srp_indirect_buf *id,
enum dma_data_direction dir, srp_rdma_t rdma_io,
int dma_map, int ext_desc)
{
struct iu_entry *iue = NULL;
struct srp_direct_buf *md = NULL;
struct scatterlist dummy, *sg = NULL;
dma_addr_t token = 0;
long err;
unsigned int done = 0;
int nmd, nsg = 0, len;
if (dma_map || ext_desc) {
iue = (struct iu_entry *) sc->SCp.ptr;
sg = sc->request_buffer;
dprintk("%p %u %u %d %d\n",
iue, sc->request_bufflen, id->len,
cmd->data_in_desc_cnt, cmd->data_out_desc_cnt);
}
nmd = id->table_desc.len / sizeof(struct srp_direct_buf);
if ((dir == DMA_FROM_DEVICE && nmd == cmd->data_in_desc_cnt) ||
(dir == DMA_TO_DEVICE && nmd == cmd->data_out_desc_cnt)) {
md = &id->desc_list[0];
goto rdma;
}
if (ext_desc && dma_map) {
md = dma_alloc_coherent(iue->target->dev, id->table_desc.len,
&token, GFP_KERNEL);
if (!md) {
eprintk("Can't get dma memory %u\n", id->table_desc.len);
return -ENOMEM;
}
sg_init_one(&dummy, md, id->table_desc.len);
sg_dma_address(&dummy) = token;
err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE,
id->table_desc.len);
if (err < 0) {
eprintk("Error copying indirect table %ld\n", err);
goto free_mem;
}
} else {
eprintk("This command uses external indirect buffer\n");
return -EINVAL;
}
rdma:
if (dma_map) {
nsg = dma_map_sg(iue->target->dev, sg, sc->use_sg, DMA_BIDIRECTIONAL);
if (!nsg) {
eprintk("fail to map %p %d\n", iue, sc->use_sg);
goto free_mem;
}
len = min(sc->request_bufflen, id->len);
} else
len = id->len;
err = rdma_io(sc, sg, nsg, md, nmd, dir, len);
if (dma_map)
dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL);
free_mem:
if (token && dma_map)
dma_free_coherent(iue->target->dev, id->table_desc.len, md, token);
return done;
}
static int data_out_desc_size(struct srp_cmd *cmd)
{
int size = 0;
u8 fmt = cmd->buf_fmt >> 4;
switch (fmt) {
case SRP_NO_DATA_DESC:
break;
case SRP_DATA_DESC_DIRECT:
size = sizeof(struct srp_direct_buf);
break;
case SRP_DATA_DESC_INDIRECT:
size = sizeof(struct srp_indirect_buf) +
sizeof(struct srp_direct_buf) * cmd->data_out_desc_cnt;
break;
default:
eprintk("client error. Invalid data_out_format %x\n", fmt);
break;
}
return size;
}
/*
* TODO: this can be called multiple times for a single command if it
* has very long data.
*/
int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd,
srp_rdma_t rdma_io, int dma_map, int ext_desc)
{
struct srp_direct_buf *md;
struct srp_indirect_buf *id;
enum dma_data_direction dir;
int offset, err = 0;
u8 format;
offset = cmd->add_cdb_len * 4;
dir = srp_cmd_direction(cmd);
if (dir == DMA_FROM_DEVICE)
offset += data_out_desc_size(cmd);
if (dir == DMA_TO_DEVICE)
format = cmd->buf_fmt >> 4;
else
format = cmd->buf_fmt & ((1U << 4) - 1);
switch (format) {
case SRP_NO_DATA_DESC:
break;
case SRP_DATA_DESC_DIRECT:
md = (struct srp_direct_buf *)
(cmd->add_data + offset);
err = srp_direct_data(sc, md, dir, rdma_io, dma_map, ext_desc);
break;
case SRP_DATA_DESC_INDIRECT:
id = (struct srp_indirect_buf *)
(cmd->add_data + offset);
err = srp_indirect_data(sc, cmd, id, dir, rdma_io, dma_map,
ext_desc);
break;
default:
eprintk("Unknown format %d %x\n", dir, format);
break;
}
return err;
}
EXPORT_SYMBOL_GPL(srp_transfer_data);
static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir)
{
struct srp_direct_buf *md;
struct srp_indirect_buf *id;
int len = 0, offset = cmd->add_cdb_len * 4;
u8 fmt;
if (dir == DMA_TO_DEVICE)
fmt = cmd->buf_fmt >> 4;
else {
fmt = cmd->buf_fmt & ((1U << 4) - 1);
offset += data_out_desc_size(cmd);
}
switch (fmt) {
case SRP_NO_DATA_DESC:
break;
case SRP_DATA_DESC_DIRECT:
md = (struct srp_direct_buf *) (cmd->add_data + offset);
len = md->len;
break;
case SRP_DATA_DESC_INDIRECT:
id = (struct srp_indirect_buf *) (cmd->add_data + offset);
len = id->len;
break;
default:
eprintk("invalid data format %x\n", fmt);
break;
}
return len;
}
int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info,
u64 addr)
{
enum dma_data_direction dir;
struct scsi_cmnd *sc;
int tag, len, err;
switch (cmd->task_attr) {
case SRP_SIMPLE_TASK:
tag = MSG_SIMPLE_TAG;
break;
case SRP_ORDERED_TASK:
tag = MSG_ORDERED_TAG;
break;
case SRP_HEAD_TASK:
tag = MSG_HEAD_TAG;
break;
default:
eprintk("Task attribute %d not supported\n", cmd->task_attr);
tag = MSG_ORDERED_TAG;
}
dir = srp_cmd_direction(cmd);
len = vscsis_data_length(cmd, dir);
dprintk("%p %x %lx %d %d %d %llx\n", info, cmd->cdb[0],
cmd->lun, dir, len, tag, (unsigned long long) cmd->tag);
sc = scsi_host_get_command(shost, dir, GFP_KERNEL);
if (!sc)
return -ENOMEM;
sc->SCp.ptr = info;
memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE);
sc->request_bufflen = len;
sc->request_buffer = (void *) (unsigned long) addr;
sc->tag = tag;
err = scsi_tgt_queue_command(sc, (struct scsi_lun *) &cmd->lun, cmd->tag);
if (err)
scsi_host_put_command(shost, sc);
return err;
}
EXPORT_SYMBOL_GPL(srp_cmd_queue);
MODULE_DESCRIPTION("SCSI RDAM Protocol lib functions");
MODULE_AUTHOR("FUJITA Tomonori");
MODULE_LICENSE("GPL");
......@@ -296,13 +296,17 @@ struct lpfc_hba {
uint32_t cfg_cr_delay;
uint32_t cfg_cr_count;
uint32_t cfg_multi_ring_support;
uint32_t cfg_multi_ring_rctl;
uint32_t cfg_multi_ring_type;
uint32_t cfg_fdmi_on;
uint32_t cfg_discovery_threads;
uint32_t cfg_max_luns;
uint32_t cfg_poll;
uint32_t cfg_poll_tmo;
uint32_t cfg_use_msi;
uint32_t cfg_sg_seg_cnt;
uint32_t cfg_sg_dma_buf_size;
uint64_t cfg_soft_wwnn;
uint64_t cfg_soft_wwpn;
uint32_t dev_loss_tmo_changed;
......@@ -355,7 +359,7 @@ struct lpfc_hba {
#define VPD_PORT 0x8 /* valid vpd port data */
#define VPD_MASK 0xf /* mask for any vpd data */
uint8_t soft_wwpn_enable;
uint8_t soft_wwn_enable;
struct timer_list fcp_poll_timer;
struct timer_list els_tmofunc;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -28,7 +28,7 @@
#define LOG_NODE 0x80 /* Node table events */
#define LOG_MISC 0x400 /* Miscellaneous events */
#define LOG_SLI 0x800 /* SLI events */
#define LOG_CHK_COND 0x1000 /* FCP Check condition flag */
#define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */
#define LOG_LIBDFC 0x2000 /* Libdfc events */
#define LOG_ALL_MSG 0xffff /* LOG all messages */
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -198,7 +198,7 @@ struct lpfc_sli {
int fcp_ring; /* ring used for FCP initiator commands */
int next_ring;
int ip_ring; /* ring used for IP network drv cmds */
int extra_ring; /* extra ring used for other protocols */
struct lpfc_sli_stat slistat; /* SLI statistical info */
struct list_head mboxq;
......
......@@ -18,7 +18,7 @@
* included with this package. *
*******************************************************************/
#define LPFC_DRIVER_VERSION "8.1.10"
#define LPFC_DRIVER_VERSION "8.1.11"
#define LPFC_DRIVER_NAME "lpfc"
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -390,7 +390,7 @@ static struct sysfs_entry {
{ "optrom_ctl", &sysfs_optrom_ctl_attr, },
{ "vpd", &sysfs_vpd_attr, 1 },
{ "sfp", &sysfs_sfp_attr, 1 },
{ 0 },
{ NULL },
};
void
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册