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: David Howells <dhowells@redhat.com>
This commit is contained in:
commit
4796b71fbb
@ -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.
|
||||
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.
|
||||
|
||||
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().
|
||||
|
||||
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 @@ found_port:
|
||||
|
||||
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 @@ found_port:
|
||||
|
||||
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 @@ fail1:
|
||||
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
|
||||
|
958
drivers/scsi/ibmvscsi/ibmvstgt.c
Normal file
958
drivers/scsi/ibmvscsi/ibmvstgt.c
Normal file
@ -0,0 +1,958 @@
|
||||
/*
|
||||
* IBM eServer i/pSeries Virtual SCSI Target Driver
|
||||
* Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp.
|
||||
* Santiago Leon (santil@us.ibm.com) IBM Corp.
|
||||
* Linda Xie (lxie@us.ibm.com) IBM Corp.
|
||||
*
|
||||
* Copyright (C) 2005-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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||
* USA
|
||||
*/
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/module.h>
|
||||
#include <scsi/scsi.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_tgt.h>
|
||||
#include <scsi/libsrp.h>
|
||||
#include <asm/hvcall.h>
|
||||
#include <asm/iommu.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/vio.h>
|
||||
|
||||
#include "ibmvscsi.h"
|
||||
|
||||
#define INITIAL_SRP_LIMIT 16
|
||||
#define DEFAULT_MAX_SECTORS 512
|
||||
|
||||
#define TGT_NAME "ibmvstgt"
|
||||
|
||||
/*
|
||||
* Hypervisor calls.
|
||||
*/
|
||||
#define h_copy_rdma(l, sa, sb, da, db) \
|
||||
plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db)
|
||||
#define h_send_crq(ua, l, h) \
|
||||
plpar_hcall_norets(H_SEND_CRQ, ua, l, h)
|
||||
#define h_reg_crq(ua, tok, sz)\
|
||||
plpar_hcall_norets(H_REG_CRQ, ua, tok, sz);
|
||||
#define h_free_crq(ua) \
|
||||
plpar_hcall_norets(H_FREE_CRQ, ua);
|
||||
|
||||
/* 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...)
|
||||
|
||||
struct vio_port {
|
||||
struct vio_dev *dma_dev;
|
||||
|
||||
struct crq_queue crq_queue;
|
||||
struct work_struct crq_work;
|
||||
|
||||
unsigned long liobn;
|
||||
unsigned long riobn;
|
||||
};
|
||||
|
||||
static struct workqueue_struct *vtgtd;
|
||||
|
||||
/*
|
||||
* These are fixed for the system and come from the Open Firmware device tree.
|
||||
* We just store them here to save getting them every time.
|
||||
*/
|
||||
static char system_id[64] = "";
|
||||
static char partition_name[97] = "UNKNOWN";
|
||||
static unsigned int partition_number = -1;
|
||||
|
||||
static struct vio_port *target_to_port(struct srp_target *target)
|
||||
{
|
||||
return (struct vio_port *) target->ldata;
|
||||
}
|
||||
|
||||
static inline union viosrp_iu *vio_iu(struct iu_entry *iue)
|
||||
{
|
||||
return (union viosrp_iu *) (iue->sbuf->buf);
|
||||
}
|
||||
|
||||
static int send_iu(struct iu_entry *iue, uint64_t length, uint8_t format)
|
||||
{
|
||||
struct srp_target *target = iue->target;
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
long rc, rc1;
|
||||
union {
|
||||
struct viosrp_crq cooked;
|
||||
uint64_t raw[2];
|
||||
} crq;
|
||||
|
||||
/* First copy the SRP */
|
||||
rc = h_copy_rdma(length, vport->liobn, iue->sbuf->dma,
|
||||
vport->riobn, iue->remote_token);
|
||||
|
||||
if (rc)
|
||||
eprintk("Error %ld transferring data\n", rc);
|
||||
|
||||
crq.cooked.valid = 0x80;
|
||||
crq.cooked.format = format;
|
||||
crq.cooked.reserved = 0x00;
|
||||
crq.cooked.timeout = 0x00;
|
||||
crq.cooked.IU_length = length;
|
||||
crq.cooked.IU_data_ptr = vio_iu(iue)->srp.rsp.tag;
|
||||
|
||||
if (rc == 0)
|
||||
crq.cooked.status = 0x99; /* Just needs to be non-zero */
|
||||
else
|
||||
crq.cooked.status = 0x00;
|
||||
|
||||
rc1 = h_send_crq(vport->dma_dev->unit_address, crq.raw[0], crq.raw[1]);
|
||||
|
||||
if (rc1) {
|
||||
eprintk("%ld sending response\n", rc1);
|
||||
return rc1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define SRP_RSP_SENSE_DATA_LEN 18
|
||||
|
||||
static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc,
|
||||
unsigned char status, unsigned char asc)
|
||||
{
|
||||
union viosrp_iu *iu = vio_iu(iue);
|
||||
uint64_t tag = iu->srp.rsp.tag;
|
||||
|
||||
/* If the linked bit is on and status is good */
|
||||
if (test_bit(V_LINKED, &iue->flags) && (status == NO_SENSE))
|
||||
status = 0x10;
|
||||
|
||||
memset(iu, 0, sizeof(struct srp_rsp));
|
||||
iu->srp.rsp.opcode = SRP_RSP;
|
||||
iu->srp.rsp.req_lim_delta = 1;
|
||||
iu->srp.rsp.tag = tag;
|
||||
|
||||
if (test_bit(V_DIOVER, &iue->flags))
|
||||
iu->srp.rsp.flags |= SRP_RSP_FLAG_DIOVER;
|
||||
|
||||
iu->srp.rsp.data_in_res_cnt = 0;
|
||||
iu->srp.rsp.data_out_res_cnt = 0;
|
||||
|
||||
iu->srp.rsp.flags &= ~SRP_RSP_FLAG_RSPVALID;
|
||||
|
||||
iu->srp.rsp.resp_data_len = 0;
|
||||
iu->srp.rsp.status = status;
|
||||
if (status) {
|
||||
uint8_t *sense = iu->srp.rsp.data;
|
||||
|
||||
if (sc) {
|
||||
iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
|
||||
iu->srp.rsp.sense_data_len = SCSI_SENSE_BUFFERSIZE;
|
||||
memcpy(sense, sc->sense_buffer, SCSI_SENSE_BUFFERSIZE);
|
||||
} else {
|
||||
iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION;
|
||||
iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
|
||||
iu->srp.rsp.sense_data_len = SRP_RSP_SENSE_DATA_LEN;
|
||||
|
||||
/* Valid bit and 'current errors' */
|
||||
sense[0] = (0x1 << 7 | 0x70);
|
||||
/* Sense key */
|
||||
sense[2] = status;
|
||||
/* Additional sense length */
|
||||
sense[7] = 0xa; /* 10 bytes */
|
||||
/* Additional sense code */
|
||||
sense[12] = asc;
|
||||
}
|
||||
}
|
||||
|
||||
send_iu(iue, sizeof(iu->srp.rsp) + SRP_RSP_SENSE_DATA_LEN,
|
||||
VIOSRP_SRP_FORMAT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void handle_cmd_queue(struct srp_target *target)
|
||||
{
|
||||
struct Scsi_Host *shost = target->shost;
|
||||
struct iu_entry *iue;
|
||||
struct srp_cmd *cmd;
|
||||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
retry:
|
||||
spin_lock_irqsave(&target->lock, flags);
|
||||
|
||||
list_for_each_entry(iue, &target->cmd_queue, ilist) {
|
||||
if (!test_and_set_bit(V_FLYING, &iue->flags)) {
|
||||
spin_unlock_irqrestore(&target->lock, flags);
|
||||
cmd = iue->sbuf->buf;
|
||||
err = srp_cmd_queue(shost, cmd, iue, 0);
|
||||
if (err) {
|
||||
eprintk("cannot queue cmd %p %d\n", cmd, err);
|
||||
srp_iu_put(iue);
|
||||
}
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&target->lock, flags);
|
||||
}
|
||||
|
||||
static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg,
|
||||
struct srp_direct_buf *md, int nmd,
|
||||
enum dma_data_direction dir, unsigned int rest)
|
||||
{
|
||||
struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
|
||||
struct srp_target *target = iue->target;
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
dma_addr_t token;
|
||||
long err;
|
||||
unsigned int done = 0;
|
||||
int i, sidx, soff;
|
||||
|
||||
sidx = soff = 0;
|
||||
token = sg_dma_address(sg + sidx);
|
||||
|
||||
for (i = 0; i < nmd && rest; i++) {
|
||||
unsigned int mdone, mlen;
|
||||
|
||||
mlen = min(rest, md[i].len);
|
||||
for (mdone = 0; mlen;) {
|
||||
int slen = min(sg_dma_len(sg + sidx) - soff, mlen);
|
||||
|
||||
if (dir == DMA_TO_DEVICE)
|
||||
err = h_copy_rdma(slen,
|
||||
vport->riobn,
|
||||
md[i].va + mdone,
|
||||
vport->liobn,
|
||||
token + soff);
|
||||
else
|
||||
err = h_copy_rdma(slen,
|
||||
vport->liobn,
|
||||
token + soff,
|
||||
vport->riobn,
|
||||
md[i].va + mdone);
|
||||
|
||||
if (err != H_SUCCESS) {
|
||||
eprintk("rdma error %d %d\n", dir, slen);
|
||||
goto out;
|
||||
}
|
||||
|
||||
mlen -= slen;
|
||||
mdone += slen;
|
||||
soff += slen;
|
||||
done += slen;
|
||||
|
||||
if (soff == sg_dma_len(sg + sidx)) {
|
||||
sidx++;
|
||||
soff = 0;
|
||||
token = sg_dma_address(sg + sidx);
|
||||
|
||||
if (sidx > nsg) {
|
||||
eprintk("out of sg %p %d %d\n",
|
||||
iue, sidx, nsg);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
rest -= mlen;
|
||||
}
|
||||
out:
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ibmvstgt_transfer_data(struct scsi_cmnd *sc,
|
||||
void (*done)(struct scsi_cmnd *))
|
||||
{
|
||||
struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
|
||||
int err;
|
||||
|
||||
err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1);
|
||||
|
||||
done(sc);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ibmvstgt_cmd_done(struct scsi_cmnd *sc,
|
||||
void (*done)(struct scsi_cmnd *))
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
|
||||
struct srp_target *target = iue->target;
|
||||
|
||||
dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
|
||||
|
||||
spin_lock_irqsave(&target->lock, flags);
|
||||
list_del(&iue->ilist);
|
||||
spin_unlock_irqrestore(&target->lock, flags);
|
||||
|
||||
if (sc->result != SAM_STAT_GOOD) {
|
||||
eprintk("operation failed %p %d %x\n",
|
||||
iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]);
|
||||
send_rsp(iue, sc, HARDWARE_ERROR, 0x00);
|
||||
} else
|
||||
send_rsp(iue, sc, NO_SENSE, 0x00);
|
||||
|
||||
done(sc);
|
||||
srp_iu_put(iue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int send_adapter_info(struct iu_entry *iue,
|
||||
dma_addr_t remote_buffer, uint16_t length)
|
||||
{
|
||||
struct srp_target *target = iue->target;
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
struct Scsi_Host *shost = target->shost;
|
||||
dma_addr_t data_token;
|
||||
struct mad_adapter_info_data *info;
|
||||
int err;
|
||||
|
||||
info = dma_alloc_coherent(target->dev, sizeof(*info), &data_token,
|
||||
GFP_KERNEL);
|
||||
if (!info) {
|
||||
eprintk("bad dma_alloc_coherent %p\n", target);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get remote info */
|
||||
err = h_copy_rdma(sizeof(*info), vport->riobn, remote_buffer,
|
||||
vport->liobn, data_token);
|
||||
if (err == H_SUCCESS) {
|
||||
dprintk("Client connect: %s (%d)\n",
|
||||
info->partition_name, info->partition_number);
|
||||
}
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
strcpy(info->srp_version, "16.a");
|
||||
strncpy(info->partition_name, partition_name,
|
||||
sizeof(info->partition_name));
|
||||
info->partition_number = partition_number;
|
||||
info->mad_version = 1;
|
||||
info->os_type = 2;
|
||||
info->port_max_txu[0] = shost->hostt->max_sectors << 9;
|
||||
|
||||
/* Send our info to remote */
|
||||
err = h_copy_rdma(sizeof(*info), vport->liobn, data_token,
|
||||
vport->riobn, remote_buffer);
|
||||
|
||||
dma_free_coherent(target->dev, sizeof(*info), info, data_token);
|
||||
|
||||
if (err != H_SUCCESS) {
|
||||
eprintk("Error sending adapter info %d\n", err);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void process_login(struct iu_entry *iue)
|
||||
{
|
||||
union viosrp_iu *iu = vio_iu(iue);
|
||||
struct srp_login_rsp *rsp = &iu->srp.login_rsp;
|
||||
uint64_t tag = iu->srp.rsp.tag;
|
||||
|
||||
/* TODO handle case that requested size is wrong and
|
||||
* buffer format is wrong
|
||||
*/
|
||||
memset(iu, 0, sizeof(struct srp_login_rsp));
|
||||
rsp->opcode = SRP_LOGIN_RSP;
|
||||
rsp->req_lim_delta = INITIAL_SRP_LIMIT;
|
||||
rsp->tag = tag;
|
||||
rsp->max_it_iu_len = sizeof(union srp_iu);
|
||||
rsp->max_ti_iu_len = sizeof(union srp_iu);
|
||||
/* direct and indirect */
|
||||
rsp->buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT;
|
||||
|
||||
send_iu(iue, sizeof(*rsp), VIOSRP_SRP_FORMAT);
|
||||
}
|
||||
|
||||
static inline void queue_cmd(struct iu_entry *iue)
|
||||
{
|
||||
struct srp_target *target = iue->target;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&target->lock, flags);
|
||||
list_add_tail(&iue->ilist, &target->cmd_queue);
|
||||
spin_unlock_irqrestore(&target->lock, flags);
|
||||
}
|
||||
|
||||
static int process_tsk_mgmt(struct iu_entry *iue)
|
||||
{
|
||||
union viosrp_iu *iu = vio_iu(iue);
|
||||
int fn;
|
||||
|
||||
dprintk("%p %u\n", iue, iu->srp.tsk_mgmt.tsk_mgmt_func);
|
||||
|
||||
switch (iu->srp.tsk_mgmt.tsk_mgmt_func) {
|
||||
case SRP_TSK_ABORT_TASK:
|
||||
fn = ABORT_TASK;
|
||||
break;
|
||||
case SRP_TSK_ABORT_TASK_SET:
|
||||
fn = ABORT_TASK_SET;
|
||||
break;
|
||||
case SRP_TSK_CLEAR_TASK_SET:
|
||||
fn = CLEAR_TASK_SET;
|
||||
break;
|
||||
case SRP_TSK_LUN_RESET:
|
||||
fn = LOGICAL_UNIT_RESET;
|
||||
break;
|
||||
case SRP_TSK_CLEAR_ACA:
|
||||
fn = CLEAR_ACA;
|
||||
break;
|
||||
default:
|
||||
fn = 0;
|
||||
}
|
||||
if (fn)
|
||||
scsi_tgt_tsk_mgmt_request(iue->target->shost, fn,
|
||||
iu->srp.tsk_mgmt.task_tag,
|
||||
(struct scsi_lun *) &iu->srp.tsk_mgmt.lun,
|
||||
iue);
|
||||
else
|
||||
send_rsp(iue, NULL, ILLEGAL_REQUEST, 0x20);
|
||||
|
||||
return !fn;
|
||||
}
|
||||
|
||||
static int process_mad_iu(struct iu_entry *iue)
|
||||
{
|
||||
union viosrp_iu *iu = vio_iu(iue);
|
||||
struct viosrp_adapter_info *info;
|
||||
struct viosrp_host_config *conf;
|
||||
|
||||
switch (iu->mad.empty_iu.common.type) {
|
||||
case VIOSRP_EMPTY_IU_TYPE:
|
||||
eprintk("%s\n", "Unsupported EMPTY MAD IU");
|
||||
break;
|
||||
case VIOSRP_ERROR_LOG_TYPE:
|
||||
eprintk("%s\n", "Unsupported ERROR LOG MAD IU");
|
||||
iu->mad.error_log.common.status = 1;
|
||||
send_iu(iue, sizeof(iu->mad.error_log), VIOSRP_MAD_FORMAT);
|
||||
break;
|
||||
case VIOSRP_ADAPTER_INFO_TYPE:
|
||||
info = &iu->mad.adapter_info;
|
||||
info->common.status = send_adapter_info(iue, info->buffer,
|
||||
info->common.length);
|
||||
send_iu(iue, sizeof(*info), VIOSRP_MAD_FORMAT);
|
||||
break;
|
||||
case VIOSRP_HOST_CONFIG_TYPE:
|
||||
conf = &iu->mad.host_config;
|
||||
conf->common.status = 1;
|
||||
send_iu(iue, sizeof(*conf), VIOSRP_MAD_FORMAT);
|
||||
break;
|
||||
default:
|
||||
eprintk("Unknown type %u\n", iu->srp.rsp.opcode);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int process_srp_iu(struct iu_entry *iue)
|
||||
{
|
||||
union viosrp_iu *iu = vio_iu(iue);
|
||||
int done = 1;
|
||||
u8 opcode = iu->srp.rsp.opcode;
|
||||
|
||||
switch (opcode) {
|
||||
case SRP_LOGIN_REQ:
|
||||
process_login(iue);
|
||||
break;
|
||||
case SRP_TSK_MGMT:
|
||||
done = process_tsk_mgmt(iue);
|
||||
break;
|
||||
case SRP_CMD:
|
||||
queue_cmd(iue);
|
||||
done = 0;
|
||||
break;
|
||||
case SRP_LOGIN_RSP:
|
||||
case SRP_I_LOGOUT:
|
||||
case SRP_T_LOGOUT:
|
||||
case SRP_RSP:
|
||||
case SRP_CRED_REQ:
|
||||
case SRP_CRED_RSP:
|
||||
case SRP_AER_REQ:
|
||||
case SRP_AER_RSP:
|
||||
eprintk("Unsupported type %u\n", opcode);
|
||||
break;
|
||||
default:
|
||||
eprintk("Unknown type %u\n", opcode);
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
static void process_iu(struct viosrp_crq *crq, struct srp_target *target)
|
||||
{
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
struct iu_entry *iue;
|
||||
long err, done;
|
||||
|
||||
iue = srp_iu_get(target);
|
||||
if (!iue) {
|
||||
eprintk("Error getting IU from pool, %p\n", target);
|
||||
return;
|
||||
}
|
||||
|
||||
iue->remote_token = crq->IU_data_ptr;
|
||||
|
||||
err = h_copy_rdma(crq->IU_length, vport->riobn,
|
||||
iue->remote_token, vport->liobn, iue->sbuf->dma);
|
||||
|
||||
if (err != H_SUCCESS) {
|
||||
eprintk("%ld transferring data error %p\n", err, iue);
|
||||
done = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (crq->format == VIOSRP_MAD_FORMAT)
|
||||
done = process_mad_iu(iue);
|
||||
else
|
||||
done = process_srp_iu(iue);
|
||||
out:
|
||||
if (done)
|
||||
srp_iu_put(iue);
|
||||
}
|
||||
|
||||
static irqreturn_t ibmvstgt_interrupt(int irq, void *data)
|
||||
{
|
||||
struct srp_target *target = (struct srp_target *) data;
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
|
||||
vio_disable_interrupts(vport->dma_dev);
|
||||
queue_work(vtgtd, &vport->crq_work);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int crq_queue_create(struct crq_queue *queue, struct srp_target *target)
|
||||
{
|
||||
int err;
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
|
||||
queue->msgs = (struct viosrp_crq *) get_zeroed_page(GFP_KERNEL);
|
||||
if (!queue->msgs)
|
||||
goto malloc_failed;
|
||||
queue->size = PAGE_SIZE / sizeof(*queue->msgs);
|
||||
|
||||
queue->msg_token = dma_map_single(target->dev, queue->msgs,
|
||||
queue->size * sizeof(*queue->msgs),
|
||||
DMA_BIDIRECTIONAL);
|
||||
|
||||
if (dma_mapping_error(queue->msg_token))
|
||||
goto map_failed;
|
||||
|
||||
err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token,
|
||||
PAGE_SIZE);
|
||||
|
||||
/* If the adapter was left active for some reason (like kexec)
|
||||
* try freeing and re-registering
|
||||
*/
|
||||
if (err == H_RESOURCE) {
|
||||
do {
|
||||
err = h_free_crq(vport->dma_dev->unit_address);
|
||||
} while (err == H_BUSY || H_IS_LONG_BUSY(err));
|
||||
|
||||
err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token,
|
||||
PAGE_SIZE);
|
||||
}
|
||||
|
||||
if (err != H_SUCCESS && err != 2) {
|
||||
eprintk("Error 0x%x opening virtual adapter\n", err);
|
||||
goto reg_crq_failed;
|
||||
}
|
||||
|
||||
err = request_irq(vport->dma_dev->irq, &ibmvstgt_interrupt,
|
||||
SA_INTERRUPT, "ibmvstgt", target);
|
||||
if (err)
|
||||
goto req_irq_failed;
|
||||
|
||||
vio_enable_interrupts(vport->dma_dev);
|
||||
|
||||
h_send_crq(vport->dma_dev->unit_address, 0xC001000000000000, 0);
|
||||
|
||||
queue->cur = 0;
|
||||
spin_lock_init(&queue->lock);
|
||||
|
||||
return 0;
|
||||
|
||||
req_irq_failed:
|
||||
do {
|
||||
err = h_free_crq(vport->dma_dev->unit_address);
|
||||
} while (err == H_BUSY || H_IS_LONG_BUSY(err));
|
||||
|
||||
reg_crq_failed:
|
||||
dma_unmap_single(target->dev, queue->msg_token,
|
||||
queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
|
||||
map_failed:
|
||||
free_page((unsigned long) queue->msgs);
|
||||
|
||||
malloc_failed:
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void crq_queue_destroy(struct srp_target *target)
|
||||
{
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
struct crq_queue *queue = &vport->crq_queue;
|
||||
int err;
|
||||
|
||||
free_irq(vport->dma_dev->irq, target);
|
||||
do {
|
||||
err = h_free_crq(vport->dma_dev->unit_address);
|
||||
} while (err == H_BUSY || H_IS_LONG_BUSY(err));
|
||||
|
||||
dma_unmap_single(target->dev, queue->msg_token,
|
||||
queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
|
||||
|
||||
free_page((unsigned long) queue->msgs);
|
||||
}
|
||||
|
||||
static void process_crq(struct viosrp_crq *crq, struct srp_target *target)
|
||||
{
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
dprintk("%x %x\n", crq->valid, crq->format);
|
||||
|
||||
switch (crq->valid) {
|
||||
case 0xC0:
|
||||
/* initialization */
|
||||
switch (crq->format) {
|
||||
case 0x01:
|
||||
h_send_crq(vport->dma_dev->unit_address,
|
||||
0xC002000000000000, 0);
|
||||
break;
|
||||
case 0x02:
|
||||
break;
|
||||
default:
|
||||
eprintk("Unknown format %u\n", crq->format);
|
||||
}
|
||||
break;
|
||||
case 0xFF:
|
||||
/* transport event */
|
||||
break;
|
||||
case 0x80:
|
||||
/* real payload */
|
||||
switch (crq->format) {
|
||||
case VIOSRP_SRP_FORMAT:
|
||||
case VIOSRP_MAD_FORMAT:
|
||||
process_iu(crq, target);
|
||||
break;
|
||||
case VIOSRP_OS400_FORMAT:
|
||||
case VIOSRP_AIX_FORMAT:
|
||||
case VIOSRP_LINUX_FORMAT:
|
||||
case VIOSRP_INLINE_FORMAT:
|
||||
eprintk("Unsupported format %u\n", crq->format);
|
||||
break;
|
||||
default:
|
||||
eprintk("Unknown format %u\n", crq->format);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
eprintk("unknown message type 0x%02x!?\n", crq->valid);
|
||||
}
|
||||
}
|
||||
|
||||
static inline struct viosrp_crq *next_crq(struct crq_queue *queue)
|
||||
{
|
||||
struct viosrp_crq *crq;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&queue->lock, flags);
|
||||
crq = &queue->msgs[queue->cur];
|
||||
if (crq->valid & 0x80) {
|
||||
if (++queue->cur == queue->size)
|
||||
queue->cur = 0;
|
||||
} else
|
||||
crq = NULL;
|
||||
spin_unlock_irqrestore(&queue->lock, flags);
|
||||
|
||||
return crq;
|
||||
}
|
||||
|
||||
static void handle_crq(void *data)
|
||||
{
|
||||
struct srp_target *target = (struct srp_target *) data;
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
struct viosrp_crq *crq;
|
||||
int done = 0;
|
||||
|
||||
while (!done) {
|
||||
while ((crq = next_crq(&vport->crq_queue)) != NULL) {
|
||||
process_crq(crq, target);
|
||||
crq->valid = 0x00;
|
||||
}
|
||||
|
||||
vio_enable_interrupts(vport->dma_dev);
|
||||
|
||||
crq = next_crq(&vport->crq_queue);
|
||||
if (crq) {
|
||||
vio_disable_interrupts(vport->dma_dev);
|
||||
process_crq(crq, target);
|
||||
crq->valid = 0x00;
|
||||
} else
|
||||
done = 1;
|
||||
}
|
||||
|
||||
handle_cmd_queue(target);
|
||||
}
|
||||
|
||||
|
||||
static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr;
|
||||
struct srp_target *target = iue->target;
|
||||
|
||||
dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]);
|
||||
|
||||
spin_lock_irqsave(&target->lock, flags);
|
||||
list_del(&iue->ilist);
|
||||
spin_unlock_irqrestore(&target->lock, flags);
|
||||
|
||||
srp_iu_put(iue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ibmvstgt_tsk_mgmt_response(u64 mid, int result)
|
||||
{
|
||||
struct iu_entry *iue = (struct iu_entry *) ((void *) mid);
|
||||
union viosrp_iu *iu = vio_iu(iue);
|
||||
unsigned char status, asc;
|
||||
|
||||
eprintk("%p %d\n", iue, result);
|
||||
status = NO_SENSE;
|
||||
asc = 0;
|
||||
|
||||
switch (iu->srp.tsk_mgmt.tsk_mgmt_func) {
|
||||
case SRP_TSK_ABORT_TASK:
|
||||
asc = 0x14;
|
||||
if (result)
|
||||
status = ABORTED_COMMAND;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
send_rsp(iue, NULL, status, asc);
|
||||
srp_iu_put(iue);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t system_id_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", system_id);
|
||||
}
|
||||
|
||||
static ssize_t partition_number_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%x\n", partition_number);
|
||||
}
|
||||
|
||||
static ssize_t unit_address_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
struct Scsi_Host *shost = class_to_shost(cdev);
|
||||
struct srp_target *target = host_to_srp_target(shost);
|
||||
struct vio_port *vport = target_to_port(target);
|
||||
return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address);
|
||||
}
|
||||
|
||||
static CLASS_DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL);
|
||||
static CLASS_DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL);
|
||||
static CLASS_DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL);
|
||||
|
||||
static struct class_device_attribute *ibmvstgt_attrs[] = {
|
||||
&class_device_attr_system_id,
|
||||
&class_device_attr_partition_number,
|
||||
&class_device_attr_unit_address,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct scsi_host_template ibmvstgt_sht = {
|
||||
.name = TGT_NAME,
|
||||
.module = THIS_MODULE,
|
||||
.can_queue = INITIAL_SRP_LIMIT,
|
||||
.sg_tablesize = SG_ALL,
|
||||
.use_clustering = DISABLE_CLUSTERING,
|
||||
.max_sectors = DEFAULT_MAX_SECTORS,
|
||||
.transfer_response = ibmvstgt_cmd_done,
|
||||
.transfer_data = ibmvstgt_transfer_data,
|
||||
.eh_abort_handler = ibmvstgt_eh_abort_handler,
|
||||
.tsk_mgmt_response = ibmvstgt_tsk_mgmt_response,
|
||||
.shost_attrs = ibmvstgt_attrs,
|
||||
.proc_name = TGT_NAME,
|
||||
};
|
||||
|
||||
static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id)
|
||||
{
|
||||
struct Scsi_Host *shost;
|
||||
struct srp_target *target;
|
||||
struct vio_port *vport;
|
||||
unsigned int *dma, dma_size;
|
||||
int err = -ENOMEM;
|
||||
|
||||
vport = kzalloc(sizeof(struct vio_port), GFP_KERNEL);
|
||||
if (!vport)
|
||||
return err;
|
||||
shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target));
|
||||
if (!shost)
|
||||
goto free_vport;
|
||||
err = scsi_tgt_alloc_queue(shost);
|
||||
if (err)
|
||||
goto put_host;
|
||||
|
||||
target = host_to_srp_target(shost);
|
||||
target->shost = shost;
|
||||
vport->dma_dev = dev;
|
||||
target->ldata = vport;
|
||||
err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT,
|
||||
SRP_MAX_IU_LEN);
|
||||
if (err)
|
||||
goto put_host;
|
||||
|
||||
dma = (unsigned int *) vio_get_attribute(dev, "ibm,my-dma-window",
|
||||
&dma_size);
|
||||
if (!dma || dma_size != 40) {
|
||||
eprintk("Couldn't get window property %d\n", dma_size);
|
||||
err = -EIO;
|
||||
goto free_srp_target;
|
||||
}
|
||||
vport->liobn = dma[0];
|
||||
vport->riobn = dma[5];
|
||||
|
||||
INIT_WORK(&vport->crq_work, handle_crq, target);
|
||||
|
||||
err = crq_queue_create(&vport->crq_queue, target);
|
||||
if (err)
|
||||
goto free_srp_target;
|
||||
|
||||
err = scsi_add_host(shost, target->dev);
|
||||
if (err)
|
||||
goto destroy_queue;
|
||||
return 0;
|
||||
|
||||
destroy_queue:
|
||||
crq_queue_destroy(target);
|
||||
free_srp_target:
|
||||
srp_target_free(target);
|
||||
put_host:
|
||||
scsi_host_put(shost);
|
||||
free_vport:
|
||||
kfree(vport);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ibmvstgt_remove(struct vio_dev *dev)
|
||||
{
|
||||
struct srp_target *target = (struct srp_target *) dev->dev.driver_data;
|
||||
struct Scsi_Host *shost = target->shost;
|
||||
struct vio_port *vport = target->ldata;
|
||||
|
||||
crq_queue_destroy(target);
|
||||
scsi_remove_host(shost);
|
||||
scsi_tgt_free_queue(shost);
|
||||
srp_target_free(target);
|
||||
kfree(vport);
|
||||
scsi_host_put(shost);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct vio_device_id ibmvstgt_device_table[] __devinitdata = {
|
||||
{"v-scsi-host", "IBM,v-scsi-host"},
|
||||
{"",""}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(vio, ibmvstgt_device_table);
|
||||
|
||||
static struct vio_driver ibmvstgt_driver = {
|
||||
.id_table = ibmvstgt_device_table,
|
||||
.probe = ibmvstgt_probe,
|
||||
.remove = ibmvstgt_remove,
|
||||
.driver = {
|
||||
.name = "ibmvscsis",
|
||||
.owner = THIS_MODULE,
|
||||
}
|
||||
};
|
||||
|
||||
static int get_system_info(void)
|
||||
{
|
||||
struct device_node *rootdn;
|
||||
const char *id, *model, *name;
|
||||
unsigned int *num;
|
||||
|
||||
rootdn = find_path_device("/");
|
||||
if (!rootdn)
|
||||
return -ENOENT;
|
||||
|
||||
model = get_property(rootdn, "model", NULL);
|
||||
id = get_property(rootdn, "system-id", NULL);
|
||||
if (model && id)
|
||||
snprintf(system_id, sizeof(system_id), "%s-%s", model, id);
|
||||
|
||||
name = get_property(rootdn, "ibm,partition-name", NULL);
|
||||
if (name)
|
||||
strncpy(partition_name, name, sizeof(partition_name));
|
||||
|
||||
num = (unsigned int *) get_property(rootdn, "ibm,partition-no", NULL);
|
||||
if (num)
|
||||
partition_number = *num;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ibmvstgt_init(void)
|
||||
{
|
||||
int err = -ENOMEM;
|
||||
|
||||
printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n");
|
||||
|
||||
vtgtd = create_workqueue("ibmvtgtd");
|
||||
if (!vtgtd)
|
||||
return err;
|
||||
|
||||
err = get_system_info();
|
||||
if (err)
|
||||
goto destroy_wq;
|
||||
|
||||
err = vio_register_driver(&ibmvstgt_driver);
|
||||
if (err)
|
||||
goto destroy_wq;
|
||||
|
||||
return 0;
|
||||
|
||||
destroy_wq:
|
||||
destroy_workqueue(vtgtd);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void ibmvstgt_exit(void)
|
||||
{
|
||||
printk("Unregister IBM virtual SCSI driver\n");
|
||||
|
||||
destroy_workqueue(vtgtd);
|
||||
vio_unregister_driver(&ibmvstgt_driver);
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("IBM Virtual SCSI Target");
|
||||
MODULE_AUTHOR("Santiago Leon");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(ibmvstgt_init);
|
||||
module_exit(ibmvstgt_exit);
|
@ -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 @@ Again:
|
||||
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);
|
||||
|
||||
SAS_DPRINTK("trying to find task 0x%p\n", task);
|
||||
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);
|
||||
res = sas_scsi_find_task(task);
|
||||
|
||||
cmd->eh_eflags = 0;
|
||||
shost->host_failed--;
|
||||
|
||||
switch (res) {
|
||||
case TASK_IS_DONE:
|
||||
@ -491,6 +506,7 @@ Again:
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
441
drivers/scsi/libsrp.c
Normal file
441
drivers/scsi/libsrp.c
Normal file
@ -0,0 +1,441 @@
|
||||
/*
|
||||
* 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;
|
||||
|
@ -552,10 +552,10 @@ static CLASS_DEVICE_ATTR(board_mode, S_IRUGO | S_IWUSR,
|
||||
static CLASS_DEVICE_ATTR(issue_reset, S_IWUSR, NULL, lpfc_issue_reset);
|
||||
|
||||
|
||||
static char *lpfc_soft_wwpn_key = "C99G71SL8032A";
|
||||
static char *lpfc_soft_wwn_key = "C99G71SL8032A";
|
||||
|
||||
static ssize_t
|
||||
lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf,
|
||||
lpfc_soft_wwn_enable_store(struct class_device *cdev, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
@ -579,15 +579,15 @@ lpfc_soft_wwpn_enable_store(struct class_device *cdev, const char *buf,
|
||||
if (buf[cnt-1] == '\n')
|
||||
cnt--;
|
||||
|
||||
if ((cnt != strlen(lpfc_soft_wwpn_key)) ||
|
||||
(strncmp(buf, lpfc_soft_wwpn_key, strlen(lpfc_soft_wwpn_key)) != 0))
|
||||
if ((cnt != strlen(lpfc_soft_wwn_key)) ||
|
||||
(strncmp(buf, lpfc_soft_wwn_key, strlen(lpfc_soft_wwn_key)) != 0))
|
||||
return -EINVAL;
|
||||
|
||||
phba->soft_wwpn_enable = 1;
|
||||
phba->soft_wwn_enable = 1;
|
||||
return count;
|
||||
}
|
||||
static CLASS_DEVICE_ATTR(lpfc_soft_wwpn_enable, S_IWUSR, NULL,
|
||||
lpfc_soft_wwpn_enable_store);
|
||||
static CLASS_DEVICE_ATTR(lpfc_soft_wwn_enable, S_IWUSR, NULL,
|
||||
lpfc_soft_wwn_enable_store);
|
||||
|
||||
static ssize_t
|
||||
lpfc_soft_wwpn_show(struct class_device *cdev, char *buf)
|
||||
@ -613,12 +613,12 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
|
||||
if (buf[cnt-1] == '\n')
|
||||
cnt--;
|
||||
|
||||
if (!phba->soft_wwpn_enable || (cnt < 16) || (cnt > 18) ||
|
||||
if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) ||
|
||||
((cnt == 17) && (*buf++ != 'x')) ||
|
||||
((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))
|
||||
return -EINVAL;
|
||||
|
||||
phba->soft_wwpn_enable = 0;
|
||||
phba->soft_wwn_enable = 0;
|
||||
|
||||
memset(wwpn, 0, sizeof(wwpn));
|
||||
|
||||
@ -639,6 +639,8 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
|
||||
}
|
||||
phba->cfg_soft_wwpn = wwn_to_u64(wwpn);
|
||||
fc_host_port_name(host) = phba->cfg_soft_wwpn;
|
||||
if (phba->cfg_soft_wwnn)
|
||||
fc_host_node_name(host) = phba->cfg_soft_wwnn;
|
||||
|
||||
dev_printk(KERN_NOTICE, &phba->pcidev->dev,
|
||||
"lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
|
||||
@ -664,6 +666,66 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
|
||||
static CLASS_DEVICE_ATTR(lpfc_soft_wwpn, S_IRUGO | S_IWUSR,\
|
||||
lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
|
||||
|
||||
static ssize_t
|
||||
lpfc_soft_wwnn_show(struct class_device *cdev, char *buf)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
return snprintf(buf, PAGE_SIZE, "0x%llx\n",
|
||||
(unsigned long long)phba->cfg_soft_wwnn);
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
lpfc_soft_wwnn_store(struct class_device *cdev, const char *buf, size_t count)
|
||||
{
|
||||
struct Scsi_Host *host = class_to_shost(cdev);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
unsigned int i, j, cnt=count;
|
||||
u8 wwnn[8];
|
||||
|
||||
/* count may include a LF at end of string */
|
||||
if (buf[cnt-1] == '\n')
|
||||
cnt--;
|
||||
|
||||
if (!phba->soft_wwn_enable || (cnt < 16) || (cnt > 18) ||
|
||||
((cnt == 17) && (*buf++ != 'x')) ||
|
||||
((cnt == 18) && ((*buf++ != '0') || (*buf++ != 'x'))))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Allow wwnn to be set many times, as long as the enable is set.
|
||||
* However, once the wwpn is set, everything locks.
|
||||
*/
|
||||
|
||||
memset(wwnn, 0, sizeof(wwnn));
|
||||
|
||||
/* Validate and store the new name */
|
||||
for (i=0, j=0; i < 16; i++) {
|
||||
if ((*buf >= 'a') && (*buf <= 'f'))
|
||||
j = ((j << 4) | ((*buf++ -'a') + 10));
|
||||
else if ((*buf >= 'A') && (*buf <= 'F'))
|
||||
j = ((j << 4) | ((*buf++ -'A') + 10));
|
||||
else if ((*buf >= '0') && (*buf <= '9'))
|
||||
j = ((j << 4) | (*buf++ -'0'));
|
||||
else
|
||||
return -EINVAL;
|
||||
if (i % 2) {
|
||||
wwnn[i/2] = j & 0xff;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
phba->cfg_soft_wwnn = wwn_to_u64(wwnn);
|
||||
|
||||
dev_printk(KERN_NOTICE, &phba->pcidev->dev,
|
||||
"lpfc%d: soft_wwnn set. Value will take effect upon "
|
||||
"setting of the soft_wwpn\n", phba->brd_no);
|
||||
|
||||
return count;
|
||||
}
|
||||
static CLASS_DEVICE_ATTR(lpfc_soft_wwnn, S_IRUGO | S_IWUSR,\
|
||||
lpfc_soft_wwnn_show, lpfc_soft_wwnn_store);
|
||||
|
||||
|
||||
static int lpfc_poll = 0;
|
||||
module_param(lpfc_poll, int, 0);
|
||||
@ -802,12 +864,11 @@ static CLASS_DEVICE_ATTR(lpfc_devloss_tmo, S_IRUGO | S_IWUSR,
|
||||
# LOG_MBOX 0x4 Mailbox events
|
||||
# LOG_INIT 0x8 Initialization events
|
||||
# LOG_LINK_EVENT 0x10 Link events
|
||||
# LOG_IP 0x20 IP traffic history
|
||||
# LOG_FCP 0x40 FCP traffic history
|
||||
# LOG_NODE 0x80 Node table events
|
||||
# LOG_MISC 0x400 Miscellaneous events
|
||||
# LOG_SLI 0x800 SLI events
|
||||
# LOG_CHK_COND 0x1000 FCP Check condition flag
|
||||
# LOG_FCP_ERROR 0x1000 Only log FCP errors
|
||||
# LOG_LIBDFC 0x2000 LIBDFC events
|
||||
# LOG_ALL_MSG 0xffff LOG all messages
|
||||
*/
|
||||
@ -915,6 +976,22 @@ LPFC_ATTR_RW(cr_count, 1, 1, 255, "A count of I/O completions after which an "
|
||||
LPFC_ATTR_R(multi_ring_support, 1, 1, 2, "Determines number of primary "
|
||||
"SLI rings to spread IOCB entries across");
|
||||
|
||||
/*
|
||||
# lpfc_multi_ring_rctl: If lpfc_multi_ring_support is enabled, this
|
||||
# identifies what rctl value to configure the additional ring for.
|
||||
# Value range is [1,0xff]. Default value is 4 (Unsolicated Data).
|
||||
*/
|
||||
LPFC_ATTR_R(multi_ring_rctl, FC_UNSOL_DATA, 1,
|
||||
255, "Identifies RCTL for additional ring configuration");
|
||||
|
||||
/*
|
||||
# lpfc_multi_ring_type: If lpfc_multi_ring_support is enabled, this
|
||||
# identifies what type value to configure the additional ring for.
|
||||
# Value range is [1,0xff]. Default value is 5 (LLC/SNAP).
|
||||
*/
|
||||
LPFC_ATTR_R(multi_ring_type, FC_LLC_SNAP, 1,
|
||||
255, "Identifies TYPE for additional ring configuration");
|
||||
|
||||
/*
|
||||
# lpfc_fdmi_on: controls FDMI support.
|
||||
# 0 = no FDMI support
|
||||
@ -946,6 +1023,15 @@ LPFC_ATTR_R(max_luns, 255, 0, 65535,
|
||||
LPFC_ATTR_RW(poll_tmo, 10, 1, 255,
|
||||
"Milliseconds driver will wait between polling FCP ring");
|
||||
|
||||
/*
|
||||
# lpfc_use_msi: Use MSI (Message Signaled Interrupts) in systems that
|
||||
# support this feature
|
||||
# 0 = MSI disabled (default)
|
||||
# 1 = MSI enabled
|
||||
# Value range is [0,1]. Default value is 0.
|
||||
*/
|
||||
LPFC_ATTR_R(use_msi, 0, 0, 1, "Use Message Signaled Interrupts, if possible");
|
||||
|
||||
|
||||
struct class_device_attribute *lpfc_host_attrs[] = {
|
||||
&class_device_attr_info,
|
||||
@ -974,6 +1060,8 @@ struct class_device_attribute *lpfc_host_attrs[] = {
|
||||
&class_device_attr_lpfc_cr_delay,
|
||||
&class_device_attr_lpfc_cr_count,
|
||||
&class_device_attr_lpfc_multi_ring_support,
|
||||
&class_device_attr_lpfc_multi_ring_rctl,
|
||||
&class_device_attr_lpfc_multi_ring_type,
|
||||
&class_device_attr_lpfc_fdmi_on,
|
||||
&class_device_attr_lpfc_max_luns,
|
||||
&class_device_attr_nport_evt_cnt,
|
||||
@ -982,8 +1070,10 @@ struct class_device_attribute *lpfc_host_attrs[] = {
|
||||
&class_device_attr_issue_reset,
|
||||
&class_device_attr_lpfc_poll,
|
||||
&class_device_attr_lpfc_poll_tmo,
|
||||
&class_device_attr_lpfc_use_msi,
|
||||
&class_device_attr_lpfc_soft_wwnn,
|
||||
&class_device_attr_lpfc_soft_wwpn,
|
||||
&class_device_attr_lpfc_soft_wwpn_enable,
|
||||
&class_device_attr_lpfc_soft_wwn_enable,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@ -1771,6 +1861,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
||||
lpfc_cr_delay_init(phba, lpfc_cr_delay);
|
||||
lpfc_cr_count_init(phba, lpfc_cr_count);
|
||||
lpfc_multi_ring_support_init(phba, lpfc_multi_ring_support);
|
||||
lpfc_multi_ring_rctl_init(phba, lpfc_multi_ring_rctl);
|
||||
lpfc_multi_ring_type_init(phba, lpfc_multi_ring_type);
|
||||
lpfc_lun_queue_depth_init(phba, lpfc_lun_queue_depth);
|
||||
lpfc_fcp_class_init(phba, lpfc_fcp_class);
|
||||
lpfc_use_adisc_init(phba, lpfc_use_adisc);
|
||||
@ -1782,9 +1874,11 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
||||
lpfc_discovery_threads_init(phba, lpfc_discovery_threads);
|
||||
lpfc_max_luns_init(phba, lpfc_max_luns);
|
||||
lpfc_poll_tmo_init(phba, lpfc_poll_tmo);
|
||||
lpfc_use_msi_init(phba, lpfc_use_msi);
|
||||
lpfc_devloss_tmo_init(phba, lpfc_devloss_tmo);
|
||||
lpfc_nodev_tmo_init(phba, lpfc_nodev_tmo);
|
||||
phba->cfg_poll = lpfc_poll;
|
||||
phba->cfg_soft_wwnn = 0L;
|
||||
phba->cfg_soft_wwpn = 0L;
|
||||
|
||||
/*
|
||||
|
@ -558,6 +558,14 @@ lpfc_cmpl_ct_cmd_rsnn_nn(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_cmpl_ct_cmd_rff_id(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
struct lpfc_iocbq * rspiocb)
|
||||
{
|
||||
lpfc_cmpl_ct_cmd_rft_id(phba, cmdiocb, rspiocb);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_get_hba_sym_node_name(struct lpfc_hba * phba, uint8_t * symbp)
|
||||
{
|
||||
@ -629,6 +637,8 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
|
||||
bpl->tus.f.bdeSize = RNN_REQUEST_SZ;
|
||||
else if (cmdcode == SLI_CTNS_RSNN_NN)
|
||||
bpl->tus.f.bdeSize = RSNN_REQUEST_SZ;
|
||||
else if (cmdcode == SLI_CTNS_RFF_ID)
|
||||
bpl->tus.f.bdeSize = RFF_REQUEST_SZ;
|
||||
else
|
||||
bpl->tus.f.bdeSize = 0;
|
||||
bpl->tus.w = le32_to_cpu(bpl->tus.w);
|
||||
@ -660,6 +670,17 @@ lpfc_ns_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
|
||||
cmpl = lpfc_cmpl_ct_cmd_rft_id;
|
||||
break;
|
||||
|
||||
case SLI_CTNS_RFF_ID:
|
||||
CtReq->CommandResponse.bits.CmdRsp =
|
||||
be16_to_cpu(SLI_CTNS_RFF_ID);
|
||||
CtReq->un.rff.PortId = be32_to_cpu(phba->fc_myDID);
|
||||
CtReq->un.rff.feature_res = 0;
|
||||
CtReq->un.rff.feature_tgt = 0;
|
||||
CtReq->un.rff.type_code = FC_FCP_DATA;
|
||||
CtReq->un.rff.feature_init = 1;
|
||||
cmpl = lpfc_cmpl_ct_cmd_rff_id;
|
||||
break;
|
||||
|
||||
case SLI_CTNS_RNN_ID:
|
||||
CtReq->CommandResponse.bits.CmdRsp =
|
||||
be16_to_cpu(SLI_CTNS_RNN_ID);
|
||||
@ -934,7 +955,8 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
|
||||
ae = (ATTRIBUTE_ENTRY *) ((uint8_t *) rh + size);
|
||||
ae->ad.bits.AttrType = be16_to_cpu(OS_NAME_VERSION);
|
||||
sprintf(ae->un.OsNameVersion, "%s %s %s",
|
||||
init_utsname()->sysname, init_utsname()->release,
|
||||
init_utsname()->sysname,
|
||||
init_utsname()->release,
|
||||
init_utsname()->version);
|
||||
len = strlen(ae->un.OsNameVersion);
|
||||
len += (len & 3) ? (4 - (len & 3)) : 4;
|
||||
|
@ -243,6 +243,7 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
|
||||
struct serv_parm *sp, IOCB_t *irsp)
|
||||
{
|
||||
LPFC_MBOXQ_t *mbox;
|
||||
struct lpfc_dmabuf *mp;
|
||||
int rc;
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
@ -307,10 +308,14 @@ lpfc_cmpl_els_flogi_fabric(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
|
||||
|
||||
rc = lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT | MBX_STOP_IOCB);
|
||||
if (rc == MBX_NOT_FINISHED)
|
||||
goto fail_free_mbox;
|
||||
goto fail_issue_reg_login;
|
||||
|
||||
return 0;
|
||||
|
||||
fail_issue_reg_login:
|
||||
mp = (struct lpfc_dmabuf *) mbox->context1;
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
fail_free_mbox:
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
fail:
|
||||
@ -657,6 +662,12 @@ lpfc_plogi_confirm_nport(struct lpfc_hba * phba, struct lpfc_dmabuf *prsp,
|
||||
uint8_t name[sizeof (struct lpfc_name)];
|
||||
uint32_t rc;
|
||||
|
||||
/* Fabric nodes can have the same WWPN so we don't bother searching
|
||||
* by WWPN. Just return the ndlp that was given to us.
|
||||
*/
|
||||
if (ndlp->nlp_type & NLP_FABRIC)
|
||||
return ndlp;
|
||||
|
||||
lp = (uint32_t *) prsp->virt;
|
||||
sp = (struct serv_parm *) ((uint8_t *) lp + sizeof (uint32_t));
|
||||
memset(name, 0, sizeof (struct lpfc_name));
|
||||
@ -1122,7 +1133,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
mempool_free(mbox,
|
||||
phba->mbox_mem_pool);
|
||||
lpfc_disc_flush_list(phba);
|
||||
psli->ring[(psli->ip_ring)].
|
||||
psli->ring[(psli->extra_ring)].
|
||||
flag &=
|
||||
~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[(psli->fcp_ring)].
|
||||
@ -1851,6 +1862,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
IOCB_t *irsp;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
LPFC_MBOXQ_t *mbox = NULL;
|
||||
struct lpfc_dmabuf *mp;
|
||||
|
||||
irsp = &rspiocb->iocb;
|
||||
|
||||
@ -1862,6 +1874,11 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
/* Check to see if link went down during discovery */
|
||||
if ((lpfc_els_chk_latt(phba)) || !ndlp) {
|
||||
if (mbox) {
|
||||
mp = (struct lpfc_dmabuf *) mbox->context1;
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
mempool_free( mbox, phba->mbox_mem_pool);
|
||||
}
|
||||
goto out;
|
||||
@ -1893,9 +1910,7 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
}
|
||||
/* NOTE: we should have messages for unsuccessful
|
||||
reglogin */
|
||||
mempool_free( mbox, phba->mbox_mem_pool);
|
||||
} else {
|
||||
mempool_free( mbox, phba->mbox_mem_pool);
|
||||
/* Do not call NO_LIST for lpfc_els_abort'ed ELS cmds */
|
||||
if (!((irsp->ulpStatus == IOSTAT_LOCAL_REJECT) &&
|
||||
((irsp->un.ulpWord[4] == IOERR_SLI_ABORTED) ||
|
||||
@ -1907,6 +1922,12 @@ lpfc_cmpl_els_acc(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
}
|
||||
}
|
||||
}
|
||||
mp = (struct lpfc_dmabuf *) mbox->context1;
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
}
|
||||
out:
|
||||
if (ndlp) {
|
||||
@ -2644,6 +2665,7 @@ lpfc_els_handle_rscn(struct lpfc_hba * phba)
|
||||
ndlp->nlp_type |= NLP_FABRIC;
|
||||
ndlp->nlp_prev_state = ndlp->nlp_state;
|
||||
ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
|
||||
lpfc_issue_els_plogi(phba, NameServer_DID, 0);
|
||||
/* Wait for NameServer login cmpl before we can
|
||||
continue */
|
||||
@ -3039,7 +3061,7 @@ lpfc_els_rcv_farp(struct lpfc_hba * phba,
|
||||
/* FARP-REQ received from DID <did> */
|
||||
lpfc_printf_log(phba,
|
||||
KERN_INFO,
|
||||
LOG_IP,
|
||||
LOG_ELS,
|
||||
"%d:0601 FARP-REQ received from DID x%x\n",
|
||||
phba->brd_no, did);
|
||||
|
||||
@ -3101,7 +3123,7 @@ lpfc_els_rcv_farpr(struct lpfc_hba * phba,
|
||||
/* FARP-RSP received from DID <did> */
|
||||
lpfc_printf_log(phba,
|
||||
KERN_INFO,
|
||||
LOG_IP,
|
||||
LOG_ELS,
|
||||
"%d:0600 FARP-RSP received from DID x%x\n",
|
||||
phba->brd_no, did);
|
||||
|
||||
|
@ -525,7 +525,7 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
psli = &phba->sli;
|
||||
mb = &pmb->mb;
|
||||
/* Since we don't do discovery right now, turn these off here */
|
||||
psli->ring[psli->ip_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[psli->extra_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[psli->fcp_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[psli->next_ring].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
|
||||
@ -641,7 +641,7 @@ out:
|
||||
if (rc == MBX_NOT_FINISHED) {
|
||||
mempool_free(pmb, phba->mbox_mem_pool);
|
||||
lpfc_disc_flush_list(phba);
|
||||
psli->ring[(psli->ip_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
phba->hba_state = LPFC_HBA_READY;
|
||||
@ -672,6 +672,8 @@ lpfc_mbx_cmpl_read_sparam(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
|
||||
memcpy((uint8_t *) & phba->fc_sparam, (uint8_t *) mp->virt,
|
||||
sizeof (struct serv_parm));
|
||||
if (phba->cfg_soft_wwnn)
|
||||
u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
|
||||
if (phba->cfg_soft_wwpn)
|
||||
u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
|
||||
memcpy((uint8_t *) & phba->fc_nodename,
|
||||
@ -696,7 +698,7 @@ out:
|
||||
== MBX_NOT_FINISHED) {
|
||||
mempool_free( pmb, phba->mbox_mem_pool);
|
||||
lpfc_disc_flush_list(phba);
|
||||
psli->ring[(psli->ip_ring)].flag &=
|
||||
psli->ring[(psli->extra_ring)].flag &=
|
||||
~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[(psli->fcp_ring)].flag &=
|
||||
~LPFC_STOP_IOCB_EVENT;
|
||||
@ -715,6 +717,9 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
|
||||
{
|
||||
int i;
|
||||
LPFC_MBOXQ_t *sparam_mbox, *cfglink_mbox;
|
||||
struct lpfc_dmabuf *mp;
|
||||
int rc;
|
||||
|
||||
sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
|
||||
@ -793,16 +798,27 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, READ_LA_VAR *la)
|
||||
if (sparam_mbox) {
|
||||
lpfc_read_sparam(phba, sparam_mbox);
|
||||
sparam_mbox->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
|
||||
lpfc_sli_issue_mbox(phba, sparam_mbox,
|
||||
rc = lpfc_sli_issue_mbox(phba, sparam_mbox,
|
||||
(MBX_NOWAIT | MBX_STOP_IOCB));
|
||||
if (rc == MBX_NOT_FINISHED) {
|
||||
mp = (struct lpfc_dmabuf *) sparam_mbox->context1;
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
mempool_free(sparam_mbox, phba->mbox_mem_pool);
|
||||
if (cfglink_mbox)
|
||||
mempool_free(cfglink_mbox, phba->mbox_mem_pool);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cfglink_mbox) {
|
||||
phba->hba_state = LPFC_LOCAL_CFG_LINK;
|
||||
lpfc_config_link(phba, cfglink_mbox);
|
||||
cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
|
||||
lpfc_sli_issue_mbox(phba, cfglink_mbox,
|
||||
rc = lpfc_sli_issue_mbox(phba, cfglink_mbox,
|
||||
(MBX_NOWAIT | MBX_STOP_IOCB));
|
||||
if (rc == MBX_NOT_FINISHED)
|
||||
mempool_free(cfglink_mbox, phba->mbox_mem_pool);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1067,6 +1083,7 @@ lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RNN_ID);
|
||||
lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RSNN_NN);
|
||||
lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFT_ID);
|
||||
lpfc_ns_cmd(phba, ndlp, SLI_CTNS_RFF_ID);
|
||||
}
|
||||
|
||||
phba->fc_ns_retry = 0;
|
||||
@ -1423,7 +1440,7 @@ lpfc_check_sli_ndlp(struct lpfc_hba * phba,
|
||||
if (iocb->context1 == (uint8_t *) ndlp)
|
||||
return 1;
|
||||
}
|
||||
} else if (pring->ringno == psli->ip_ring) {
|
||||
} else if (pring->ringno == psli->extra_ring) {
|
||||
|
||||
} else if (pring->ringno == psli->fcp_ring) {
|
||||
/* Skip match check if waiting to relogin to FCP target */
|
||||
@ -1680,21 +1697,38 @@ lpfc_matchdid(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, uint32_t did)
|
||||
struct lpfc_nodelist *
|
||||
lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
|
||||
{
|
||||
struct lpfc_nodelist *ndlp, *next_ndlp;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
struct list_head *lists[]={&phba->fc_nlpunmap_list,
|
||||
&phba->fc_nlpmap_list,
|
||||
&phba->fc_plogi_list,
|
||||
&phba->fc_adisc_list,
|
||||
&phba->fc_reglogin_list,
|
||||
&phba->fc_prli_list,
|
||||
&phba->fc_npr_list,
|
||||
&phba->fc_unused_list};
|
||||
uint32_t search[]={NLP_SEARCH_UNMAPPED,
|
||||
NLP_SEARCH_MAPPED,
|
||||
NLP_SEARCH_PLOGI,
|
||||
NLP_SEARCH_ADISC,
|
||||
NLP_SEARCH_REGLOGIN,
|
||||
NLP_SEARCH_PRLI,
|
||||
NLP_SEARCH_NPR,
|
||||
NLP_SEARCH_UNUSED};
|
||||
int i;
|
||||
uint32_t data1;
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
if (order & NLP_SEARCH_UNMAPPED) {
|
||||
list_for_each_entry_safe(ndlp, next_ndlp,
|
||||
&phba->fc_nlpunmap_list, nlp_listp) {
|
||||
for (i = 0; i < ARRAY_SIZE(lists); i++ ) {
|
||||
if (!(order & search[i]))
|
||||
continue;
|
||||
list_for_each_entry(ndlp, lists[i], nlp_listp) {
|
||||
if (lpfc_matchdid(phba, ndlp, did)) {
|
||||
data1 = (((uint32_t) ndlp->nlp_state << 24) |
|
||||
((uint32_t) ndlp->nlp_xri << 16) |
|
||||
((uint32_t) ndlp->nlp_type << 8) |
|
||||
((uint32_t) ndlp->nlp_rpi & 0xff));
|
||||
/* FIND node DID unmapped */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0929 FIND node DID unmapped"
|
||||
"%d:0929 FIND node DID "
|
||||
" Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
@ -1704,177 +1738,12 @@ lpfc_findnode_did(struct lpfc_hba * phba, uint32_t order, uint32_t did)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (order & NLP_SEARCH_MAPPED) {
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list,
|
||||
nlp_listp) {
|
||||
if (lpfc_matchdid(phba, ndlp, did)) {
|
||||
|
||||
data1 = (((uint32_t) ndlp->nlp_state << 24) |
|
||||
((uint32_t) ndlp->nlp_xri << 16) |
|
||||
((uint32_t) ndlp->nlp_type << 8) |
|
||||
((uint32_t) ndlp->nlp_rpi & 0xff));
|
||||
/* FIND node DID mapped */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0930 FIND node DID mapped "
|
||||
"Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
ndlp->nlp_flag, data1);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return ndlp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (order & NLP_SEARCH_PLOGI) {
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list,
|
||||
nlp_listp) {
|
||||
if (lpfc_matchdid(phba, ndlp, did)) {
|
||||
|
||||
data1 = (((uint32_t) ndlp->nlp_state << 24) |
|
||||
((uint32_t) ndlp->nlp_xri << 16) |
|
||||
((uint32_t) ndlp->nlp_type << 8) |
|
||||
((uint32_t) ndlp->nlp_rpi & 0xff));
|
||||
/* LOG change to PLOGI */
|
||||
/* FIND node DID plogi */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0908 FIND node DID plogi "
|
||||
"Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
ndlp->nlp_flag, data1);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return ndlp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (order & NLP_SEARCH_ADISC) {
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,
|
||||
nlp_listp) {
|
||||
if (lpfc_matchdid(phba, ndlp, did)) {
|
||||
|
||||
data1 = (((uint32_t) ndlp->nlp_state << 24) |
|
||||
((uint32_t) ndlp->nlp_xri << 16) |
|
||||
((uint32_t) ndlp->nlp_type << 8) |
|
||||
((uint32_t) ndlp->nlp_rpi & 0xff));
|
||||
/* LOG change to ADISC */
|
||||
/* FIND node DID adisc */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0931 FIND node DID adisc "
|
||||
"Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
ndlp->nlp_flag, data1);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return ndlp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (order & NLP_SEARCH_REGLOGIN) {
|
||||
list_for_each_entry_safe(ndlp, next_ndlp,
|
||||
&phba->fc_reglogin_list, nlp_listp) {
|
||||
if (lpfc_matchdid(phba, ndlp, did)) {
|
||||
|
||||
data1 = (((uint32_t) ndlp->nlp_state << 24) |
|
||||
((uint32_t) ndlp->nlp_xri << 16) |
|
||||
((uint32_t) ndlp->nlp_type << 8) |
|
||||
((uint32_t) ndlp->nlp_rpi & 0xff));
|
||||
/* LOG change to REGLOGIN */
|
||||
/* FIND node DID reglogin */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0901 FIND node DID reglogin"
|
||||
" Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
ndlp->nlp_flag, data1);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return ndlp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (order & NLP_SEARCH_PRLI) {
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list,
|
||||
nlp_listp) {
|
||||
if (lpfc_matchdid(phba, ndlp, did)) {
|
||||
|
||||
data1 = (((uint32_t) ndlp->nlp_state << 24) |
|
||||
((uint32_t) ndlp->nlp_xri << 16) |
|
||||
((uint32_t) ndlp->nlp_type << 8) |
|
||||
((uint32_t) ndlp->nlp_rpi & 0xff));
|
||||
/* LOG change to PRLI */
|
||||
/* FIND node DID prli */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0902 FIND node DID prli "
|
||||
"Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
ndlp->nlp_flag, data1);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return ndlp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (order & NLP_SEARCH_NPR) {
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
|
||||
nlp_listp) {
|
||||
if (lpfc_matchdid(phba, ndlp, did)) {
|
||||
|
||||
data1 = (((uint32_t) ndlp->nlp_state << 24) |
|
||||
((uint32_t) ndlp->nlp_xri << 16) |
|
||||
((uint32_t) ndlp->nlp_type << 8) |
|
||||
((uint32_t) ndlp->nlp_rpi & 0xff));
|
||||
/* LOG change to NPR */
|
||||
/* FIND node DID npr */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0903 FIND node DID npr "
|
||||
"Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
ndlp->nlp_flag, data1);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return ndlp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (order & NLP_SEARCH_UNUSED) {
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,
|
||||
nlp_listp) {
|
||||
if (lpfc_matchdid(phba, ndlp, did)) {
|
||||
|
||||
data1 = (((uint32_t) ndlp->nlp_state << 24) |
|
||||
((uint32_t) ndlp->nlp_xri << 16) |
|
||||
((uint32_t) ndlp->nlp_type << 8) |
|
||||
((uint32_t) ndlp->nlp_rpi & 0xff));
|
||||
/* LOG change to UNUSED */
|
||||
/* FIND node DID unused */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0905 FIND node DID unused "
|
||||
"Data: x%p x%x x%x x%x\n",
|
||||
phba->brd_no,
|
||||
ndlp, ndlp->nlp_DID,
|
||||
ndlp->nlp_flag, data1);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return ndlp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
/* FIND node did <did> NOT FOUND */
|
||||
lpfc_printf_log(phba,
|
||||
KERN_INFO,
|
||||
LOG_NODE,
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_NODE,
|
||||
"%d:0932 FIND node did x%x NOT FOUND Data: x%x\n",
|
||||
phba->brd_no, did, order);
|
||||
|
||||
/* no match found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -2036,7 +1905,7 @@ lpfc_disc_start(struct lpfc_hba * phba)
|
||||
if (rc == MBX_NOT_FINISHED) {
|
||||
mempool_free( mbox, phba->mbox_mem_pool);
|
||||
lpfc_disc_flush_list(phba);
|
||||
psli->ring[(psli->ip_ring)].flag &=
|
||||
psli->ring[(psli->extra_ring)].flag &=
|
||||
~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[(psli->fcp_ring)].flag &=
|
||||
~LPFC_STOP_IOCB_EVENT;
|
||||
@ -2415,7 +2284,7 @@ lpfc_disc_timeout_handler(struct lpfc_hba *phba)
|
||||
|
||||
if (clrlaerr) {
|
||||
lpfc_disc_flush_list(phba);
|
||||
psli->ring[(psli->ip_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[(psli->extra_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[(psli->fcp_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
psli->ring[(psli->next_ring)].flag &= ~LPFC_STOP_IOCB_EVENT;
|
||||
phba->hba_state = LPFC_HBA_READY;
|
||||
|
@ -42,14 +42,14 @@
|
||||
#define FCELSSIZE 1024 /* maximum ELS transfer size */
|
||||
|
||||
#define LPFC_FCP_RING 0 /* ring 0 for FCP initiator commands */
|
||||
#define LPFC_IP_RING 1 /* ring 1 for IP commands */
|
||||
#define LPFC_EXTRA_RING 1 /* ring 1 for other protocols */
|
||||
#define LPFC_ELS_RING 2 /* ring 2 for ELS commands */
|
||||
#define LPFC_FCP_NEXT_RING 3
|
||||
|
||||
#define SLI2_IOCB_CMD_R0_ENTRIES 172 /* SLI-2 FCP command ring entries */
|
||||
#define SLI2_IOCB_RSP_R0_ENTRIES 134 /* SLI-2 FCP response ring entries */
|
||||
#define SLI2_IOCB_CMD_R1_ENTRIES 4 /* SLI-2 IP command ring entries */
|
||||
#define SLI2_IOCB_RSP_R1_ENTRIES 4 /* SLI-2 IP response ring entries */
|
||||
#define SLI2_IOCB_CMD_R1_ENTRIES 4 /* SLI-2 extra command ring entries */
|
||||
#define SLI2_IOCB_RSP_R1_ENTRIES 4 /* SLI-2 extra response ring entries */
|
||||
#define SLI2_IOCB_CMD_R1XTRA_ENTRIES 36 /* SLI-2 extra FCP cmd ring entries */
|
||||
#define SLI2_IOCB_RSP_R1XTRA_ENTRIES 52 /* SLI-2 extra FCP rsp ring entries */
|
||||
#define SLI2_IOCB_CMD_R2_ENTRIES 20 /* SLI-2 ELS command ring entries */
|
||||
@ -121,6 +121,20 @@ struct lpfc_sli_ct_request {
|
||||
|
||||
uint32_t rsvd[7];
|
||||
} rft;
|
||||
struct rff {
|
||||
uint32_t PortId;
|
||||
uint8_t reserved[2];
|
||||
#ifdef __BIG_ENDIAN_BITFIELD
|
||||
uint8_t feature_res:6;
|
||||
uint8_t feature_init:1;
|
||||
uint8_t feature_tgt:1;
|
||||
#else /* __LITTLE_ENDIAN_BITFIELD */
|
||||
uint8_t feature_tgt:1;
|
||||
uint8_t feature_init:1;
|
||||
uint8_t feature_res:6;
|
||||
#endif
|
||||
uint8_t type_code; /* type=8 for FCP */
|
||||
} rff;
|
||||
struct rnn {
|
||||
uint32_t PortId; /* For RNN_ID requests */
|
||||
uint8_t wwnn[8];
|
||||
@ -136,6 +150,7 @@ struct lpfc_sli_ct_request {
|
||||
#define SLI_CT_REVISION 1
|
||||
#define GID_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 260)
|
||||
#define RFT_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 228)
|
||||
#define RFF_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 235)
|
||||
#define RNN_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request) - 252)
|
||||
#define RSNN_REQUEST_SZ (sizeof(struct lpfc_sli_ct_request))
|
||||
|
||||
@ -225,6 +240,7 @@ struct lpfc_sli_ct_request {
|
||||
#define SLI_CTNS_RNN_ID 0x0213
|
||||
#define SLI_CTNS_RCS_ID 0x0214
|
||||
#define SLI_CTNS_RFT_ID 0x0217
|
||||
#define SLI_CTNS_RFF_ID 0x021F
|
||||
#define SLI_CTNS_RSPN_ID 0x0218
|
||||
#define SLI_CTNS_RPT_ID 0x021A
|
||||
#define SLI_CTNS_RIP_NN 0x0235
|
||||
@ -1089,12 +1105,6 @@ typedef struct {
|
||||
#define PCI_DEVICE_ID_ZEPHYR_SCSP 0xfe11
|
||||
#define PCI_DEVICE_ID_ZEPHYR_DCSP 0xfe12
|
||||
|
||||
#define PCI_SUBSYSTEM_ID_LP11000S 0xfc11
|
||||
#define PCI_SUBSYSTEM_ID_LP11002S 0xfc12
|
||||
#define PCI_SUBSYSTEM_ID_LPE11000S 0xfc21
|
||||
#define PCI_SUBSYSTEM_ID_LPE11002S 0xfc22
|
||||
#define PCI_SUBSYSTEM_ID_LPE11010S 0xfc2A
|
||||
|
||||
#define JEDEC_ID_ADDRESS 0x0080001c
|
||||
#define FIREFLY_JEDEC_ID 0x1ACC
|
||||
#define SUPERFLY_JEDEC_ID 0x0020
|
||||
@ -1284,6 +1294,10 @@ typedef struct { /* FireFly BIU registers */
|
||||
#define CMD_FCP_IREAD_CX 0x1B
|
||||
#define CMD_FCP_ICMND_CR 0x1C
|
||||
#define CMD_FCP_ICMND_CX 0x1D
|
||||
#define CMD_FCP_TSEND_CX 0x1F
|
||||
#define CMD_FCP_TRECEIVE_CX 0x21
|
||||
#define CMD_FCP_TRSP_CX 0x23
|
||||
#define CMD_FCP_AUTO_TRSP_CX 0x29
|
||||
|
||||
#define CMD_ADAPTER_MSG 0x20
|
||||
#define CMD_ADAPTER_DUMP 0x22
|
||||
@ -1310,6 +1324,9 @@ typedef struct { /* FireFly BIU registers */
|
||||
#define CMD_FCP_IREAD64_CX 0x9B
|
||||
#define CMD_FCP_ICMND64_CR 0x9C
|
||||
#define CMD_FCP_ICMND64_CX 0x9D
|
||||
#define CMD_FCP_TSEND64_CX 0x9F
|
||||
#define CMD_FCP_TRECEIVE64_CX 0xA1
|
||||
#define CMD_FCP_TRSP64_CX 0xA3
|
||||
|
||||
#define CMD_GEN_REQUEST64_CR 0xC2
|
||||
#define CMD_GEN_REQUEST64_CX 0xC3
|
||||
|
@ -268,6 +268,8 @@ lpfc_config_port_post(struct lpfc_hba * phba)
|
||||
kfree(mp);
|
||||
pmb->context1 = NULL;
|
||||
|
||||
if (phba->cfg_soft_wwnn)
|
||||
u64_to_wwn(phba->cfg_soft_wwnn, phba->fc_sparam.nodeName.u.wwn);
|
||||
if (phba->cfg_soft_wwpn)
|
||||
u64_to_wwn(phba->cfg_soft_wwpn, phba->fc_sparam.portName.u.wwn);
|
||||
memcpy(&phba->fc_nodename, &phba->fc_sparam.nodeName,
|
||||
@ -349,8 +351,8 @@ lpfc_config_port_post(struct lpfc_hba * phba)
|
||||
phba->hba_state = LPFC_LINK_DOWN;
|
||||
|
||||
/* Only process IOCBs on ring 0 till hba_state is READY */
|
||||
if (psli->ring[psli->ip_ring].cmdringaddr)
|
||||
psli->ring[psli->ip_ring].flag |= LPFC_STOP_IOCB_EVENT;
|
||||
if (psli->ring[psli->extra_ring].cmdringaddr)
|
||||
psli->ring[psli->extra_ring].flag |= LPFC_STOP_IOCB_EVENT;
|
||||
if (psli->ring[psli->fcp_ring].cmdringaddr)
|
||||
psli->ring[psli->fcp_ring].flag |= LPFC_STOP_IOCB_EVENT;
|
||||
if (psli->ring[psli->next_ring].cmdringaddr)
|
||||
@ -517,7 +519,8 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
|
||||
struct lpfc_sli_ring *pring;
|
||||
uint32_t event_data;
|
||||
|
||||
if (phba->work_hs & HS_FFER6) {
|
||||
if (phba->work_hs & HS_FFER6 ||
|
||||
phba->work_hs & HS_FFER5) {
|
||||
/* Re-establishing Link */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
|
||||
"%d:1301 Re-establishing Link "
|
||||
@ -611,7 +614,7 @@ lpfc_handle_latt(struct lpfc_hba * phba)
|
||||
pmb->mbox_cmpl = lpfc_mbx_cmpl_read_la;
|
||||
rc = lpfc_sli_issue_mbox (phba, pmb, (MBX_NOWAIT | MBX_STOP_IOCB));
|
||||
if (rc == MBX_NOT_FINISHED)
|
||||
goto lpfc_handle_latt_free_mp;
|
||||
goto lpfc_handle_latt_free_mbuf;
|
||||
|
||||
/* Clear Link Attention in HA REG */
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
@ -621,6 +624,8 @@ lpfc_handle_latt(struct lpfc_hba * phba)
|
||||
|
||||
return;
|
||||
|
||||
lpfc_handle_latt_free_mbuf:
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
lpfc_handle_latt_free_mp:
|
||||
kfree(mp);
|
||||
lpfc_handle_latt_free_pmb:
|
||||
@ -802,19 +807,13 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
|
||||
{
|
||||
lpfc_vpd_t *vp;
|
||||
uint16_t dev_id = phba->pcidev->device;
|
||||
uint16_t dev_subid = phba->pcidev->subsystem_device;
|
||||
uint8_t hdrtype;
|
||||
int max_speed;
|
||||
char * ports;
|
||||
struct {
|
||||
char * name;
|
||||
int max_speed;
|
||||
char * ports;
|
||||
char * bus;
|
||||
} m = {"<Unknown>", 0, "", ""};
|
||||
} m = {"<Unknown>", 0, ""};
|
||||
|
||||
pci_read_config_byte(phba->pcidev, PCI_HEADER_TYPE, &hdrtype);
|
||||
ports = (hdrtype == 0x80) ? "2-port " : "";
|
||||
if (mdp && mdp[0] != '\0'
|
||||
&& descp && descp[0] != '\0')
|
||||
return;
|
||||
@ -834,130 +833,93 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
|
||||
|
||||
switch (dev_id) {
|
||||
case PCI_DEVICE_ID_FIREFLY:
|
||||
m = (typeof(m)){"LP6000", max_speed, "", "PCI"};
|
||||
m = (typeof(m)){"LP6000", max_speed, "PCI"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SUPERFLY:
|
||||
if (vp->rev.biuRev >= 1 && vp->rev.biuRev <= 3)
|
||||
m = (typeof(m)){"LP7000", max_speed, "", "PCI"};
|
||||
m = (typeof(m)){"LP7000", max_speed, "PCI"};
|
||||
else
|
||||
m = (typeof(m)){"LP7000E", max_speed, "", "PCI"};
|
||||
m = (typeof(m)){"LP7000E", max_speed, "PCI"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_DRAGONFLY:
|
||||
m = (typeof(m)){"LP8000", max_speed, "", "PCI"};
|
||||
m = (typeof(m)){"LP8000", max_speed, "PCI"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_CENTAUR:
|
||||
if (FC_JEDEC_ID(vp->rev.biuRev) == CENTAUR_2G_JEDEC_ID)
|
||||
m = (typeof(m)){"LP9002", max_speed, "", "PCI"};
|
||||
m = (typeof(m)){"LP9002", max_speed, "PCI"};
|
||||
else
|
||||
m = (typeof(m)){"LP9000", max_speed, "", "PCI"};
|
||||
m = (typeof(m)){"LP9000", max_speed, "PCI"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_RFLY:
|
||||
m = (typeof(m)){"LP952", max_speed, "", "PCI"};
|
||||
m = (typeof(m)){"LP952", max_speed, "PCI"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_PEGASUS:
|
||||
m = (typeof(m)){"LP9802", max_speed, "", "PCI-X"};
|
||||
m = (typeof(m)){"LP9802", max_speed, "PCI-X"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_THOR:
|
||||
if (hdrtype == 0x80)
|
||||
m = (typeof(m)){"LP10000DC",
|
||||
max_speed, ports, "PCI-X"};
|
||||
else
|
||||
m = (typeof(m)){"LP10000",
|
||||
max_speed, ports, "PCI-X"};
|
||||
m = (typeof(m)){"LP10000", max_speed, "PCI-X"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_VIPER:
|
||||
m = (typeof(m)){"LPX1000", max_speed, "", "PCI-X"};
|
||||
m = (typeof(m)){"LPX1000", max_speed, "PCI-X"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_PFLY:
|
||||
m = (typeof(m)){"LP982", max_speed, "", "PCI-X"};
|
||||
m = (typeof(m)){"LP982", max_speed, "PCI-X"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_TFLY:
|
||||
if (hdrtype == 0x80)
|
||||
m = (typeof(m)){"LP1050DC", max_speed, ports, "PCI-X"};
|
||||
else
|
||||
m = (typeof(m)){"LP1050", max_speed, ports, "PCI-X"};
|
||||
m = (typeof(m)){"LP1050", max_speed, "PCI-X"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_HELIOS:
|
||||
if (hdrtype == 0x80)
|
||||
m = (typeof(m)){"LP11002", max_speed, ports, "PCI-X2"};
|
||||
else
|
||||
m = (typeof(m)){"LP11000", max_speed, ports, "PCI-X2"};
|
||||
m = (typeof(m)){"LP11000", max_speed, "PCI-X2"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_HELIOS_SCSP:
|
||||
m = (typeof(m)){"LP11000-SP", max_speed, ports, "PCI-X2"};
|
||||
m = (typeof(m)){"LP11000-SP", max_speed, "PCI-X2"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_HELIOS_DCSP:
|
||||
m = (typeof(m)){"LP11002-SP", max_speed, ports, "PCI-X2"};
|
||||
m = (typeof(m)){"LP11002-SP", max_speed, "PCI-X2"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_NEPTUNE:
|
||||
if (hdrtype == 0x80)
|
||||
m = (typeof(m)){"LPe1002", max_speed, ports, "PCIe"};
|
||||
else
|
||||
m = (typeof(m)){"LPe1000", max_speed, ports, "PCIe"};
|
||||
m = (typeof(m)){"LPe1000", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_NEPTUNE_SCSP:
|
||||
m = (typeof(m)){"LPe1000-SP", max_speed, ports, "PCIe"};
|
||||
m = (typeof(m)){"LPe1000-SP", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_NEPTUNE_DCSP:
|
||||
m = (typeof(m)){"LPe1002-SP", max_speed, ports, "PCIe"};
|
||||
m = (typeof(m)){"LPe1002-SP", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_BMID:
|
||||
m = (typeof(m)){"LP1150", max_speed, ports, "PCI-X2"};
|
||||
m = (typeof(m)){"LP1150", max_speed, "PCI-X2"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_BSMB:
|
||||
m = (typeof(m)){"LP111", max_speed, ports, "PCI-X2"};
|
||||
m = (typeof(m)){"LP111", max_speed, "PCI-X2"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZEPHYR:
|
||||
if (hdrtype == 0x80)
|
||||
m = (typeof(m)){"LPe11002", max_speed, ports, "PCIe"};
|
||||
else
|
||||
m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"};
|
||||
m = (typeof(m)){"LPe11000", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZEPHYR_SCSP:
|
||||
m = (typeof(m)){"LPe11000", max_speed, ports, "PCIe"};
|
||||
m = (typeof(m)){"LPe11000", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZEPHYR_DCSP:
|
||||
m = (typeof(m)){"LPe11002-SP", max_speed, ports, "PCIe"};
|
||||
m = (typeof(m)){"LPe11002-SP", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZMID:
|
||||
m = (typeof(m)){"LPe1150", max_speed, ports, "PCIe"};
|
||||
m = (typeof(m)){"LPe1150", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_ZSMB:
|
||||
m = (typeof(m)){"LPe111", max_speed, ports, "PCIe"};
|
||||
m = (typeof(m)){"LPe111", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LP101:
|
||||
m = (typeof(m)){"LP101", max_speed, ports, "PCI-X"};
|
||||
m = (typeof(m)){"LP101", max_speed, "PCI-X"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LP10000S:
|
||||
m = (typeof(m)){"LP10000-S", max_speed, ports, "PCI"};
|
||||
m = (typeof(m)){"LP10000-S", max_speed, "PCI"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LP11000S:
|
||||
m = (typeof(m)){"LP11000-S", max_speed,
|
||||
"PCI-X2"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_LPE11000S:
|
||||
switch (dev_subid) {
|
||||
case PCI_SUBSYSTEM_ID_LP11000S:
|
||||
m = (typeof(m)){"LP11000-S", max_speed,
|
||||
ports, "PCI-X2"};
|
||||
break;
|
||||
case PCI_SUBSYSTEM_ID_LP11002S:
|
||||
m = (typeof(m)){"LP11002-S", max_speed,
|
||||
ports, "PCI-X2"};
|
||||
break;
|
||||
case PCI_SUBSYSTEM_ID_LPE11000S:
|
||||
m = (typeof(m)){"LPe11000-S", max_speed,
|
||||
ports, "PCIe"};
|
||||
break;
|
||||
case PCI_SUBSYSTEM_ID_LPE11002S:
|
||||
m = (typeof(m)){"LPe11002-S", max_speed,
|
||||
ports, "PCIe"};
|
||||
break;
|
||||
case PCI_SUBSYSTEM_ID_LPE11010S:
|
||||
m = (typeof(m)){"LPe11010-S", max_speed,
|
||||
"10-port ", "PCIe"};
|
||||
break;
|
||||
default:
|
||||
m = (typeof(m)){ NULL };
|
||||
break;
|
||||
}
|
||||
m = (typeof(m)){"LPe11000-S", max_speed,
|
||||
"PCIe"};
|
||||
break;
|
||||
default:
|
||||
m = (typeof(m)){ NULL };
|
||||
@ -968,8 +930,8 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
|
||||
snprintf(mdp, 79,"%s", m.name);
|
||||
if (descp && descp[0] == '\0')
|
||||
snprintf(descp, 255,
|
||||
"Emulex %s %dGb %s%s Fibre Channel Adapter",
|
||||
m.name, m.max_speed, m.ports, m.bus);
|
||||
"Emulex %s %dGb %s Fibre Channel Adapter",
|
||||
m.name, m.max_speed, m.bus);
|
||||
}
|
||||
|
||||
/**************************************************/
|
||||
@ -1651,6 +1613,14 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
||||
if (error)
|
||||
goto out_remove_host;
|
||||
|
||||
if (phba->cfg_use_msi) {
|
||||
error = pci_enable_msi(phba->pcidev);
|
||||
if (error)
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "%d:0452 "
|
||||
"Enable MSI failed, continuing with "
|
||||
"IRQ\n", phba->brd_no);
|
||||
}
|
||||
|
||||
error = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED,
|
||||
LPFC_DRIVER_NAME, phba);
|
||||
if (error) {
|
||||
@ -1730,6 +1700,7 @@ out_free_irq:
|
||||
lpfc_stop_timer(phba);
|
||||
phba->work_hba_events = 0;
|
||||
free_irq(phba->pcidev->irq, phba);
|
||||
pci_disable_msi(phba->pcidev);
|
||||
out_free_sysfs_attr:
|
||||
lpfc_free_sysfs_attr(phba);
|
||||
out_remove_host:
|
||||
@ -1796,6 +1767,7 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
|
||||
|
||||
/* Release the irq reservation */
|
||||
free_irq(phba->pcidev->irq, phba);
|
||||
pci_disable_msi(phba->pcidev);
|
||||
|
||||
lpfc_cleanup(phba, 0);
|
||||
lpfc_stop_timer(phba);
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -739,7 +739,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
|
||||
uint32_t evt)
|
||||
{
|
||||
struct lpfc_iocbq *cmdiocb, *rspiocb;
|
||||
struct lpfc_dmabuf *pcmd, *prsp;
|
||||
struct lpfc_dmabuf *pcmd, *prsp, *mp;
|
||||
uint32_t *lp;
|
||||
IOCB_t *irsp;
|
||||
struct serv_parm *sp;
|
||||
@ -829,6 +829,9 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
|
||||
NLP_REGLOGIN_LIST);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
mp = (struct lpfc_dmabuf *)mbox->context1;
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
} else {
|
||||
mempool_free(mbox, phba->mbox_mem_pool);
|
||||
@ -1620,8 +1623,8 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
|
||||
* or discovery in progress for this node. Starting discovery
|
||||
* here will affect the counting of discovery threads.
|
||||
*/
|
||||
if ((!(ndlp->nlp_flag & NLP_DELAY_TMO)) &&
|
||||
(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
|
||||
if (!(ndlp->nlp_flag & NLP_DELAY_TMO) &&
|
||||
!(ndlp->nlp_flag & NLP_NPR_2B_DISC)){
|
||||
if (ndlp->nlp_flag & NLP_NPR_ADISC) {
|
||||
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
|
||||
ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
|
||||
|
@ -297,8 +297,10 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
||||
uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm;
|
||||
uint32_t resp_info = fcprsp->rspStatus2;
|
||||
uint32_t scsi_status = fcprsp->rspStatus3;
|
||||
uint32_t *lp;
|
||||
uint32_t host_status = DID_OK;
|
||||
uint32_t rsplen = 0;
|
||||
uint32_t logit = LOG_FCP | LOG_FCP_ERROR;
|
||||
|
||||
/*
|
||||
* If this is a task management command, there is no
|
||||
@ -310,10 +312,25 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
|
||||
"%d:0730 FCP command failed: RSP "
|
||||
"Data: x%x x%x x%x x%x x%x x%x\n",
|
||||
phba->brd_no, resp_info, scsi_status,
|
||||
if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen) {
|
||||
uint32_t snslen = be32_to_cpu(fcprsp->rspSnsLen);
|
||||
if (snslen > SCSI_SENSE_BUFFERSIZE)
|
||||
snslen = SCSI_SENSE_BUFFERSIZE;
|
||||
|
||||
if (resp_info & RSP_LEN_VALID)
|
||||
rsplen = be32_to_cpu(fcprsp->rspRspLen);
|
||||
memcpy(cmnd->sense_buffer, &fcprsp->rspInfo0 + rsplen, snslen);
|
||||
}
|
||||
lp = (uint32_t *)cmnd->sense_buffer;
|
||||
|
||||
if (!scsi_status && (resp_info & RESID_UNDER))
|
||||
logit = LOG_FCP;
|
||||
|
||||
lpfc_printf_log(phba, KERN_WARNING, logit,
|
||||
"%d:0730 FCP command x%x failed: x%x SNS x%x x%x "
|
||||
"Data: x%x x%x x%x x%x x%x\n",
|
||||
phba->brd_no, cmnd->cmnd[0], scsi_status,
|
||||
be32_to_cpu(*lp), be32_to_cpu(*(lp + 3)), resp_info,
|
||||
be32_to_cpu(fcprsp->rspResId),
|
||||
be32_to_cpu(fcprsp->rspSnsLen),
|
||||
be32_to_cpu(fcprsp->rspRspLen),
|
||||
@ -328,14 +345,6 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
||||
}
|
||||
}
|
||||
|
||||
if ((resp_info & SNS_LEN_VALID) && fcprsp->rspSnsLen) {
|
||||
uint32_t snslen = be32_to_cpu(fcprsp->rspSnsLen);
|
||||
if (snslen > SCSI_SENSE_BUFFERSIZE)
|
||||
snslen = SCSI_SENSE_BUFFERSIZE;
|
||||
|
||||
memcpy(cmnd->sense_buffer, &fcprsp->rspInfo0 + rsplen, snslen);
|
||||
}
|
||||
|
||||
cmnd->resid = 0;
|
||||
if (resp_info & RESID_UNDER) {
|
||||
cmnd->resid = be32_to_cpu(fcprsp->rspResId);
|
||||
@ -378,7 +387,7 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
||||
*/
|
||||
} else if ((scsi_status == SAM_STAT_GOOD) && fcpi_parm &&
|
||||
(cmnd->sc_data_direction == DMA_FROM_DEVICE)) {
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP,
|
||||
lpfc_printf_log(phba, KERN_WARNING, LOG_FCP | LOG_FCP_ERROR,
|
||||
"%d:0734 FCP Read Check Error Data: "
|
||||
"x%x x%x x%x x%x\n", phba->brd_no,
|
||||
be32_to_cpu(fcpcmd->fcpDl),
|
||||
@ -670,6 +679,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
|
||||
struct lpfc_iocbq *iocbqrsp;
|
||||
int ret;
|
||||
|
||||
if (!rdata->pnode)
|
||||
return FAILED;
|
||||
|
||||
lpfc_cmd->rdata = rdata;
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, lun,
|
||||
FCP_TARGET_RESET);
|
||||
@ -976,20 +988,34 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
||||
|
||||
lpfc_block_error_handler(cmnd);
|
||||
spin_lock_irq(shost->host_lock);
|
||||
loopcnt = 0;
|
||||
/*
|
||||
* If target is not in a MAPPED state, delay the reset until
|
||||
* target is rediscovered or devloss timeout expires.
|
||||
*/
|
||||
while ( 1 ) {
|
||||
if (!pnode)
|
||||
break;
|
||||
return FAILED;
|
||||
|
||||
if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
schedule_timeout_uninterruptible(msecs_to_jiffies(500));
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
loopcnt++;
|
||||
rdata = cmnd->device->hostdata;
|
||||
if (!rdata ||
|
||||
(loopcnt > ((phba->cfg_devloss_tmo * 2) + 1))) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
||||
"%d:0721 LUN Reset rport failure:"
|
||||
" cnt x%x rdata x%p\n",
|
||||
phba->brd_no, loopcnt, rdata);
|
||||
goto out;
|
||||
}
|
||||
pnode = rdata->pnode;
|
||||
if (!pnode)
|
||||
return FAILED;
|
||||
}
|
||||
if ((pnode) && (pnode->nlp_state == NLP_STE_MAPPED_NODE))
|
||||
if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -117,6 +117,10 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
|
||||
case CMD_FCP_IREAD_CX:
|
||||
case CMD_FCP_ICMND_CR:
|
||||
case CMD_FCP_ICMND_CX:
|
||||
case CMD_FCP_TSEND_CX:
|
||||
case CMD_FCP_TRSP_CX:
|
||||
case CMD_FCP_TRECEIVE_CX:
|
||||
case CMD_FCP_AUTO_TRSP_CX:
|
||||
case CMD_ADAPTER_MSG:
|
||||
case CMD_ADAPTER_DUMP:
|
||||
case CMD_XMIT_SEQUENCE64_CR:
|
||||
@ -131,6 +135,9 @@ lpfc_sli_iocb_cmd_type(uint8_t iocb_cmnd)
|
||||
case CMD_FCP_IREAD64_CX:
|
||||
case CMD_FCP_ICMND64_CR:
|
||||
case CMD_FCP_ICMND64_CX:
|
||||
case CMD_FCP_TSEND64_CX:
|
||||
case CMD_FCP_TRSP64_CX:
|
||||
case CMD_FCP_TRECEIVE64_CX:
|
||||
case CMD_GEN_REQUEST64_CR:
|
||||
case CMD_GEN_REQUEST64_CX:
|
||||
case CMD_XMIT_ELS_RSP64_CX:
|
||||
@ -1098,6 +1105,7 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
|
||||
lpfc_sli_pcimem_bcopy((uint32_t *) entry,
|
||||
(uint32_t *) &rspiocbq.iocb,
|
||||
sizeof (IOCB_t));
|
||||
INIT_LIST_HEAD(&(rspiocbq.list));
|
||||
irsp = &rspiocbq.iocb;
|
||||
|
||||
type = lpfc_sli_iocb_cmd_type(irsp->ulpCommand & CMD_IOCB_MASK);
|
||||
@ -1149,6 +1157,11 @@ lpfc_sli_handle_fast_ring_event(struct lpfc_hba * phba,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case LPFC_UNSOL_IOCB:
|
||||
spin_unlock_irqrestore(phba->host->host_lock, iflag);
|
||||
lpfc_sli_process_unsol_iocb(phba, pring, &rspiocbq);
|
||||
spin_lock_irqsave(phba->host->host_lock, iflag);
|
||||
break;
|
||||
default:
|
||||
if (irsp->ulpCommand == CMD_ADAPTER_MSG) {
|
||||
char adaptermsg[LPFC_MAX_ADPTMSG];
|
||||
@ -2472,13 +2485,17 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba)
|
||||
psli = &phba->sli;
|
||||
|
||||
/* Adjust cmd/rsp ring iocb entries more evenly */
|
||||
|
||||
/* Take some away from the FCP ring */
|
||||
pring = &psli->ring[psli->fcp_ring];
|
||||
pring->numCiocb -= SLI2_IOCB_CMD_R1XTRA_ENTRIES;
|
||||
pring->numRiocb -= SLI2_IOCB_RSP_R1XTRA_ENTRIES;
|
||||
pring->numCiocb -= SLI2_IOCB_CMD_R3XTRA_ENTRIES;
|
||||
pring->numRiocb -= SLI2_IOCB_RSP_R3XTRA_ENTRIES;
|
||||
|
||||
pring = &psli->ring[1];
|
||||
/* and give them to the extra ring */
|
||||
pring = &psli->ring[psli->extra_ring];
|
||||
|
||||
pring->numCiocb += SLI2_IOCB_CMD_R1XTRA_ENTRIES;
|
||||
pring->numRiocb += SLI2_IOCB_RSP_R1XTRA_ENTRIES;
|
||||
pring->numCiocb += SLI2_IOCB_CMD_R3XTRA_ENTRIES;
|
||||
@ -2488,8 +2505,8 @@ lpfc_extra_ring_setup( struct lpfc_hba *phba)
|
||||
pring->iotag_max = 4096;
|
||||
pring->num_mask = 1;
|
||||
pring->prt[0].profile = 0; /* Mask 0 */
|
||||
pring->prt[0].rctl = FC_UNSOL_DATA;
|
||||
pring->prt[0].type = 5;
|
||||
pring->prt[0].rctl = phba->cfg_multi_ring_rctl;
|
||||
pring->prt[0].type = phba->cfg_multi_ring_type;
|
||||
pring->prt[0].lpfc_sli_rcv_unsol_event = NULL;
|
||||
return 0;
|
||||
}
|
||||
@ -2505,7 +2522,7 @@ lpfc_sli_setup(struct lpfc_hba *phba)
|
||||
psli->sli_flag = 0;
|
||||
psli->fcp_ring = LPFC_FCP_RING;
|
||||
psli->next_ring = LPFC_FCP_NEXT_RING;
|
||||
psli->ip_ring = LPFC_IP_RING;
|
||||
psli->extra_ring = LPFC_EXTRA_RING;
|
||||
|
||||
psli->iocbq_lookup = NULL;
|
||||
psli->iocbq_lookup_len = 0;
|
||||
@ -2528,7 +2545,7 @@ lpfc_sli_setup(struct lpfc_hba *phba)
|
||||
pring->fast_iotag = pring->iotag_max;
|
||||
pring->num_mask = 0;
|
||||
break;
|
||||
case LPFC_IP_RING: /* ring 1 - IP */
|
||||
case LPFC_EXTRA_RING: /* ring 1 - EXTRA */
|
||||
/* numCiocb and numRiocb are used in config_port */
|
||||
pring->numCiocb = SLI2_IOCB_CMD_R1_ENTRIES;
|
||||
pring->numRiocb = SLI2_IOCB_RSP_R1_ENTRIES;
|
||||
@ -3238,6 +3255,21 @@ lpfc_intr_handler(int irq, void *dev_id)
|
||||
lpfc_sli_handle_fast_ring_event(phba,
|
||||
&phba->sli.ring[LPFC_FCP_RING],
|
||||
status);
|
||||
|
||||
if (phba->cfg_multi_ring_support == 2) {
|
||||
/*
|
||||
* Process all events on extra ring. Take the optimized path
|
||||
* for extra ring IO. Any other IO is slow path and is handled
|
||||
* by the worker thread.
|
||||
*/
|
||||
status = (ha_copy & (HA_RXMASK << (4*LPFC_EXTRA_RING)));
|
||||
status >>= (4*LPFC_EXTRA_RING);
|
||||
if (status & HA_RXATT) {
|
||||
lpfc_sli_handle_fast_ring_event(phba,
|
||||
&phba->sli.ring[LPFC_EXTRA_RING],
|
||||
status);
|
||||
}
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
|
||||
} /* lpfc_intr_handler */
|
||||
|
@ -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"
|
||||
|
||||
|
@ -73,10 +73,10 @@ static unsigned short int max_mbox_busy_wait = MBOX_BUSY_WAIT;
|
||||
module_param(max_mbox_busy_wait, ushort, 0);
|
||||
MODULE_PARM_DESC(max_mbox_busy_wait, "Maximum wait for mailbox in microseconds if busy (default=MBOX_BUSY_WAIT=10)");
|
||||
|
||||
#define RDINDOOR(adapter) readl((adapter)->base + 0x20)
|
||||
#define RDOUTDOOR(adapter) readl((adapter)->base + 0x2C)
|
||||
#define WRINDOOR(adapter,value) writel(value, (adapter)->base + 0x20)
|
||||
#define WROUTDOOR(adapter,value) writel(value, (adapter)->base + 0x2C)
|
||||
#define RDINDOOR(adapter) readl((adapter)->mmio_base + 0x20)
|
||||
#define RDOUTDOOR(adapter) readl((adapter)->mmio_base + 0x2C)
|
||||
#define WRINDOOR(adapter,value) writel(value, (adapter)->mmio_base + 0x20)
|
||||
#define WROUTDOOR(adapter,value) writel(value, (adapter)->mmio_base + 0x2C)
|
||||
|
||||
/*
|
||||
* Global variables
|
||||
@ -1386,7 +1386,8 @@ megaraid_isr_memmapped(int irq, void *devp)
|
||||
|
||||
handled = 1;
|
||||
|
||||
while( RDINDOOR(adapter) & 0x02 ) cpu_relax();
|
||||
while( RDINDOOR(adapter) & 0x02 )
|
||||
cpu_relax();
|
||||
|
||||
mega_cmd_done(adapter, completed, nstatus, status);
|
||||
|
||||
@ -4668,6 +4669,8 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
host->host_no, mega_baseport, irq);
|
||||
|
||||
adapter->base = mega_baseport;
|
||||
if (flag & BOARD_MEMMAP)
|
||||
adapter->mmio_base = (void __iomem *) mega_baseport;
|
||||
|
||||
INIT_LIST_HEAD(&adapter->free_list);
|
||||
INIT_LIST_HEAD(&adapter->pending_list);
|
||||
|
@ -801,7 +801,8 @@ typedef struct {
|
||||
clustering is available */
|
||||
u32 flag;
|
||||
|
||||
unsigned long base;
|
||||
unsigned long base;
|
||||
void __iomem *mmio_base;
|
||||
|
||||
/* mbox64 with mbox not aligned on 16-byte boundry */
|
||||
mbox64_t *una_mbox64;
|
||||
|
@ -517,7 +517,7 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp,
|
||||
* Returns the number of frames required for numnber of sge's (sge_count)
|
||||
*/
|
||||
|
||||
u32 megasas_get_frame_count(u8 sge_count)
|
||||
static u32 megasas_get_frame_count(u8 sge_count)
|
||||
{
|
||||
int num_cnt;
|
||||
int sge_bytes;
|
||||
@ -1733,7 +1733,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance,
|
||||
*
|
||||
* Tasklet to complete cmds
|
||||
*/
|
||||
void megasas_complete_cmd_dpc(unsigned long instance_addr)
|
||||
static void megasas_complete_cmd_dpc(unsigned long instance_addr)
|
||||
{
|
||||
u32 producer;
|
||||
u32 consumer;
|
||||
|
@ -589,10 +589,12 @@ static int __map_scsi_sg_data(struct device *dev, struct scsi_cmnd *cmd)
|
||||
static struct ncr_driver_setup
|
||||
driver_setup = SCSI_NCR_DRIVER_SETUP;
|
||||
|
||||
#ifndef MODULE
|
||||
#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
|
||||
static struct ncr_driver_setup
|
||||
driver_safe_setup __initdata = SCSI_NCR_DRIVER_SAFE_SETUP;
|
||||
#endif
|
||||
#endif /* !MODULE */
|
||||
|
||||
#define initverbose (driver_setup.verbose)
|
||||
#define bootverbose (np->verbose)
|
||||
@ -641,6 +643,13 @@ static struct ncr_driver_setup
|
||||
#define OPT_IARB 26
|
||||
#endif
|
||||
|
||||
#ifdef MODULE
|
||||
#define ARG_SEP ' '
|
||||
#else
|
||||
#define ARG_SEP ','
|
||||
#endif
|
||||
|
||||
#ifndef MODULE
|
||||
static char setup_token[] __initdata =
|
||||
"tags:" "mpar:"
|
||||
"spar:" "disc:"
|
||||
@ -660,12 +669,6 @@ static char setup_token[] __initdata =
|
||||
#endif
|
||||
; /* DONNOT REMOVE THIS ';' */
|
||||
|
||||
#ifdef MODULE
|
||||
#define ARG_SEP ' '
|
||||
#else
|
||||
#define ARG_SEP ','
|
||||
#endif
|
||||
|
||||
static int __init get_setup_token(char *p)
|
||||
{
|
||||
char *cur = setup_token;
|
||||
@ -682,7 +685,6 @@ static int __init get_setup_token(char *p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int __init sym53c8xx__setup(char *str)
|
||||
{
|
||||
#ifdef SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT
|
||||
@ -804,6 +806,7 @@ static int __init sym53c8xx__setup(char *str)
|
||||
#endif /* SCSI_NCR_BOOT_COMMAND_LINE_SUPPORT */
|
||||
return 1;
|
||||
}
|
||||
#endif /* !MODULE */
|
||||
|
||||
/*===================================================================
|
||||
**
|
||||
@ -8321,12 +8324,12 @@ char *ncr53c8xx; /* command line passed by insmod */
|
||||
module_param(ncr53c8xx, charp, 0);
|
||||
#endif
|
||||
|
||||
#ifndef MODULE
|
||||
static int __init ncr53c8xx_setup(char *str)
|
||||
{
|
||||
return sym53c8xx__setup(str);
|
||||
}
|
||||
|
||||
#ifndef MODULE
|
||||
__setup("ncr53c8xx=", ncr53c8xx_setup);
|
||||
#endif
|
||||
|
||||
|
@ -154,16 +154,11 @@ static int aha152x_config_cs(struct pcmcia_device *link)
|
||||
|
||||
DEBUG(0, "aha152x_config(0x%p)\n", link);
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
tuple.TupleData = tuple_data;
|
||||
tuple.TupleDataMax = 64;
|
||||
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;
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
tuple.Attributes = 0;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
|
||||
while (1) {
|
||||
if (pcmcia_get_tuple_data(link, &tuple) != 0 ||
|
||||
|
@ -136,14 +136,9 @@ static int fdomain_config(struct pcmcia_device *link)
|
||||
|
||||
DEBUG(0, "fdomain_config(0x%p)\n", link);
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
tuple.TupleData = tuple_data;
|
||||
tuple.TupleDataMax = 64;
|
||||
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;
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
|
||||
|
@ -1685,16 +1685,10 @@ static int nsp_cs_config(struct pcmcia_device *link)
|
||||
|
||||
nsp_dbg(NSP_DEBUG_INIT, "in");
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||
tuple.Attributes = 0;
|
||||
tuple.TupleData = tuple_data;
|
||||
tuple.TupleDataMax = sizeof(tuple_data);
|
||||
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));
|
||||
|
@ -208,18 +208,11 @@ static int qlogic_config(struct pcmcia_device * link)
|
||||
|
||||
DEBUG(0, "qlogic_config(0x%p)\n", link);
|
||||
|
||||
info->manf_id = link->manf_id;
|
||||
|
||||
tuple.TupleData = (cisdata_t *) tuple_data;
|
||||
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;
|
||||
|
||||
tuple.DesiredTuple = CISTPL_MANFID;
|
||||
if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) && (pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
|
||||
info->manf_id = le16_to_cpu(tuple.TupleData[0]);
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
|
||||
|
@ -722,19 +722,11 @@ SYM53C500_config(struct pcmcia_device *link)
|
||||
|
||||
DEBUG(0, "SYM53C500_config(0x%p)\n", link);
|
||||
|
||||
info->manf_id = link->manf_id;
|
||||
|
||||
tuple.TupleData = (cisdata_t *)tuple_data;
|
||||
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;
|
||||
|
||||
tuple.DesiredTuple = CISTPL_MANFID;
|
||||
if ((pcmcia_get_first_tuple(link, &tuple) == CS_SUCCESS) &&
|
||||
(pcmcia_get_tuple_data(link, &tuple) == CS_SUCCESS))
|
||||
info->manf_id = le16_to_cpu(tuple.TupleData[0]);
|
||||
|
||||
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple));
|
||||
|
@ -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
|
||||
|
@ -59,9 +59,6 @@ int
|
||||
qla2x00_initialize_adapter(scsi_qla_host_t *ha)
|
||||
{
|
||||
int rval;
|
||||
uint8_t restart_risc = 0;
|
||||
uint8_t retry;
|
||||
uint32_t wait_time;
|
||||
|
||||
/* Clear adapter flags. */
|
||||
ha->flags.online = 0;
|
||||
@ -104,87 +101,15 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
|
||||
|
||||
qla_printk(KERN_INFO, ha, "Verifying loaded RISC code...\n");
|
||||
|
||||
retry = 10;
|
||||
/*
|
||||
* Try to configure the loop.
|
||||
*/
|
||||
do {
|
||||
restart_risc = 0;
|
||||
|
||||
/* If firmware needs to be loaded */
|
||||
if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) {
|
||||
if ((rval = ha->isp_ops.chip_diag(ha)) == QLA_SUCCESS) {
|
||||
rval = qla2x00_setup_chip(ha);
|
||||
}
|
||||
}
|
||||
|
||||
if (rval == QLA_SUCCESS &&
|
||||
(rval = qla2x00_init_rings(ha)) == QLA_SUCCESS) {
|
||||
check_fw_ready_again:
|
||||
/*
|
||||
* Wait for a successful LIP up to a maximum
|
||||
* of (in seconds): RISC login timeout value,
|
||||
* RISC retry count value, and port down retry
|
||||
* value OR a minimum of 4 seconds OR If no
|
||||
* cable, only 5 seconds.
|
||||
*/
|
||||
rval = qla2x00_fw_ready(ha);
|
||||
if (rval == QLA_SUCCESS) {
|
||||
clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
|
||||
|
||||
/* Issue a marker after FW becomes ready. */
|
||||
qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
|
||||
|
||||
/*
|
||||
* Wait at most MAX_TARGET RSCNs for a stable
|
||||
* link.
|
||||
*/
|
||||
wait_time = 256;
|
||||
do {
|
||||
clear_bit(LOOP_RESYNC_NEEDED,
|
||||
&ha->dpc_flags);
|
||||
rval = qla2x00_configure_loop(ha);
|
||||
|
||||
if (test_and_clear_bit(ISP_ABORT_NEEDED,
|
||||
&ha->dpc_flags)) {
|
||||
restart_risc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* If loop state change while we were
|
||||
* discoverying devices then wait for
|
||||
* LIP to complete
|
||||
*/
|
||||
|
||||
if (atomic_read(&ha->loop_state) !=
|
||||
LOOP_READY && retry--) {
|
||||
goto check_fw_ready_again;
|
||||
}
|
||||
wait_time--;
|
||||
} while (!atomic_read(&ha->loop_down_timer) &&
|
||||
retry &&
|
||||
wait_time &&
|
||||
(test_bit(LOOP_RESYNC_NEEDED,
|
||||
&ha->dpc_flags)));
|
||||
|
||||
if (wait_time == 0)
|
||||
rval = QLA_FUNCTION_FAILED;
|
||||
} else if (ha->device_flags & DFLG_NO_CABLE)
|
||||
/* If no cable, then all is good. */
|
||||
rval = QLA_SUCCESS;
|
||||
}
|
||||
} while (restart_risc && retry--);
|
||||
|
||||
if (rval == QLA_SUCCESS) {
|
||||
clear_bit(RESET_MARKER_NEEDED, &ha->dpc_flags);
|
||||
qla2x00_marker(ha, 0, 0, MK_SYNC_ALL);
|
||||
ha->marker_needed = 0;
|
||||
|
||||
ha->flags.online = 1;
|
||||
} else {
|
||||
DEBUG2_3(printk("%s(): **** FAILED ****\n", __func__));
|
||||
if (qla2x00_isp_firmware(ha) != QLA_SUCCESS) {
|
||||
rval = ha->isp_ops.chip_diag(ha);
|
||||
if (rval)
|
||||
return (rval);
|
||||
rval = qla2x00_setup_chip(ha);
|
||||
if (rval)
|
||||
return (rval);
|
||||
}
|
||||
rval = qla2x00_init_rings(ha);
|
||||
|
||||
return (rval);
|
||||
}
|
||||
@ -2208,8 +2133,7 @@ qla2x00_update_fcport(scsi_qla_host_t *ha, fc_port_t *fcport)
|
||||
|
||||
atomic_set(&fcport->state, FCS_ONLINE);
|
||||
|
||||
if (ha->flags.init_done)
|
||||
qla2x00_reg_remote_port(ha, fcport);
|
||||
qla2x00_reg_remote_port(ha, fcport);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -95,6 +95,8 @@ MODULE_PARM_DESC(ql2xqfullrampup,
|
||||
*/
|
||||
static int qla2xxx_slave_configure(struct scsi_device * device);
|
||||
static int qla2xxx_slave_alloc(struct scsi_device *);
|
||||
static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
|
||||
static void qla2xxx_scan_start(struct Scsi_Host *);
|
||||
static void qla2xxx_slave_destroy(struct scsi_device *);
|
||||
static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
|
||||
void (*fn)(struct scsi_cmnd *));
|
||||
@ -124,6 +126,8 @@ static struct scsi_host_template qla2x00_driver_template = {
|
||||
|
||||
.slave_alloc = qla2xxx_slave_alloc,
|
||||
.slave_destroy = qla2xxx_slave_destroy,
|
||||
.scan_finished = qla2xxx_scan_finished,
|
||||
.scan_start = qla2xxx_scan_start,
|
||||
.change_queue_depth = qla2x00_change_queue_depth,
|
||||
.change_queue_type = qla2x00_change_queue_type,
|
||||
.this_id = -1,
|
||||
@ -287,7 +291,7 @@ qla24xx_pci_info_str(struct scsi_qla_host *ha, char *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
char *
|
||||
static char *
|
||||
qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str)
|
||||
{
|
||||
char un_str[10];
|
||||
@ -325,7 +329,7 @@ qla2x00_fw_version_str(struct scsi_qla_host *ha, char *str)
|
||||
return (str);
|
||||
}
|
||||
|
||||
char *
|
||||
static char *
|
||||
qla24xx_fw_version_str(struct scsi_qla_host *ha, char *str)
|
||||
{
|
||||
sprintf(str, "%d.%02d.%02d ", ha->fw_major_version,
|
||||
@ -634,7 +638,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
|
||||
* Note:
|
||||
* Only return FAILED if command not returned by firmware.
|
||||
**************************************************************************/
|
||||
int
|
||||
static int
|
||||
qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
|
||||
@ -771,7 +775,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
|
||||
* SUCCESS/FAILURE (defined as macro in scsi.h).
|
||||
*
|
||||
**************************************************************************/
|
||||
int
|
||||
static int
|
||||
qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
|
||||
@ -902,7 +906,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
|
||||
* SUCCESS/FAILURE (defined as macro in scsi.h).
|
||||
*
|
||||
**************************************************************************/
|
||||
int
|
||||
static int
|
||||
qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
|
||||
@ -963,7 +967,7 @@ eh_bus_reset_done:
|
||||
*
|
||||
* Note:
|
||||
**************************************************************************/
|
||||
int
|
||||
static int
|
||||
qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
|
||||
{
|
||||
scsi_qla_host_t *ha = to_qla_host(cmd->device->host);
|
||||
@ -1366,6 +1370,29 @@ qla24xx_disable_intrs(scsi_qla_host_t *ha)
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
qla2xxx_scan_start(struct Scsi_Host *shost)
|
||||
{
|
||||
scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata;
|
||||
|
||||
set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags);
|
||||
set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags);
|
||||
set_bit(RSCN_UPDATE, &ha->dpc_flags);
|
||||
}
|
||||
|
||||
static int
|
||||
qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time)
|
||||
{
|
||||
scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata;
|
||||
|
||||
if (!ha->host)
|
||||
return 1;
|
||||
if (time > ha->loop_reset_delay * HZ)
|
||||
return 1;
|
||||
|
||||
return atomic_read(&ha->loop_state) == LOOP_READY;
|
||||
}
|
||||
|
||||
/*
|
||||
* PCI driver interface
|
||||
*/
|
||||
@ -1377,10 +1404,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
struct Scsi_Host *host;
|
||||
scsi_qla_host_t *ha;
|
||||
unsigned long flags = 0;
|
||||
unsigned long wait_switch = 0;
|
||||
char pci_info[20];
|
||||
char fw_str[30];
|
||||
fc_port_t *fcport;
|
||||
struct scsi_host_template *sht;
|
||||
|
||||
if (pci_enable_device(pdev))
|
||||
@ -1631,30 +1656,19 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
|
||||
ha->isp_ops.enable_intrs(ha);
|
||||
|
||||
/* v2.19.5b6 */
|
||||
/*
|
||||
* Wait around max loop_reset_delay secs for the devices to come
|
||||
* on-line. We don't want Linux scanning before we are ready.
|
||||
*
|
||||
*/
|
||||
for (wait_switch = jiffies + (ha->loop_reset_delay * HZ);
|
||||
time_before(jiffies,wait_switch) &&
|
||||
!(ha->device_flags & (DFLG_NO_CABLE | DFLG_FABRIC_DEVICES))
|
||||
&& (ha->device_flags & SWITCH_FOUND) ;) {
|
||||
|
||||
qla2x00_check_fabric_devices(ha);
|
||||
|
||||
msleep(10);
|
||||
}
|
||||
|
||||
pci_set_drvdata(pdev, ha);
|
||||
|
||||
ha->flags.init_done = 1;
|
||||
ha->flags.online = 1;
|
||||
|
||||
num_hosts++;
|
||||
|
||||
ret = scsi_add_host(host, &pdev->dev);
|
||||
if (ret)
|
||||
goto probe_failed;
|
||||
|
||||
scsi_scan_host(host);
|
||||
|
||||
qla2x00_alloc_sysfs_attr(ha);
|
||||
|
||||
qla2x00_init_host_attr(ha);
|
||||
@ -1669,10 +1683,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
ha->flags.enable_64bit_addressing ? '+': '-', ha->host_no,
|
||||
ha->isp_ops.fw_version_str(ha, fw_str));
|
||||
|
||||
/* Go with fc_rport registration. */
|
||||
list_for_each_entry(fcport, &ha->fcports, list)
|
||||
qla2x00_reg_remote_port(ha, fcport);
|
||||
|
||||
return 0;
|
||||
|
||||
probe_failed:
|
||||
|
@ -449,7 +449,7 @@ nvram_data_to_access_addr(uint32_t naddr)
|
||||
return FARX_ACCESS_NVRAM_DATA | naddr;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
qla24xx_read_flash_dword(scsi_qla_host_t *ha, uint32_t addr)
|
||||
{
|
||||
int rval;
|
||||
@ -490,7 +490,7 @@ qla24xx_read_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
|
||||
return dwptr;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data)
|
||||
{
|
||||
int rval;
|
||||
@ -512,7 +512,7 @@ qla24xx_write_flash_dword(scsi_qla_host_t *ha, uint32_t addr, uint32_t data)
|
||||
return rval;
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
|
||||
uint8_t *flash_id)
|
||||
{
|
||||
@ -537,7 +537,7 @@ qla24xx_get_flash_manufacturer(scsi_qla_host_t *ha, uint8_t *man_id,
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr,
|
||||
uint32_t dwords)
|
||||
{
|
||||
|
@ -71,7 +71,7 @@ void __dump_registers(struct scsi_qla_host *ha)
|
||||
readw(&ha->reg->u1.isp4010.nvram));
|
||||
}
|
||||
|
||||
else if (is_qla4022(ha)) {
|
||||
else if (is_qla4022(ha) | is_qla4032(ha)) {
|
||||
printk(KERN_INFO "0x%02X intr_mask = 0x%08X\n",
|
||||
(uint8_t) offsetof(struct isp_reg,
|
||||
u1.isp4022.intr_mask),
|
||||
@ -119,7 +119,7 @@ void __dump_registers(struct scsi_qla_host *ha)
|
||||
readw(&ha->reg->u2.isp4010.port_err_status));
|
||||
}
|
||||
|
||||
else if (is_qla4022(ha)) {
|
||||
else if (is_qla4022(ha) | is_qla4032(ha)) {
|
||||
printk(KERN_INFO "Page 0 Registers:\n");
|
||||
printk(KERN_INFO "0x%02X ext_hw_conf = 0x%08X\n",
|
||||
(uint8_t) offsetof(struct isp_reg,
|
||||
|
@ -40,7 +40,11 @@
|
||||
|
||||
#ifndef PCI_DEVICE_ID_QLOGIC_ISP4022
|
||||
#define PCI_DEVICE_ID_QLOGIC_ISP4022 0x4022
|
||||
#endif /* */
|
||||
#endif
|
||||
|
||||
#ifndef PCI_DEVICE_ID_QLOGIC_ISP4032
|
||||
#define PCI_DEVICE_ID_QLOGIC_ISP4032 0x4032
|
||||
#endif
|
||||
|
||||
#define QLA_SUCCESS 0
|
||||
#define QLA_ERROR 1
|
||||
@ -277,7 +281,6 @@ struct scsi_qla_host {
|
||||
#define AF_INTERRUPTS_ON 6 /* 0x00000040 Not Used */
|
||||
#define AF_GET_CRASH_RECORD 7 /* 0x00000080 */
|
||||
#define AF_LINK_UP 8 /* 0x00000100 */
|
||||
#define AF_TOPCAT_CHIP_PRESENT 9 /* 0x00000200 */
|
||||
#define AF_IRQ_ATTACHED 10 /* 0x00000400 */
|
||||
#define AF_ISNS_CMD_IN_PROCESS 12 /* 0x00001000 */
|
||||
#define AF_ISNS_CMD_DONE 13 /* 0x00002000 */
|
||||
@ -317,16 +320,17 @@ struct scsi_qla_host {
|
||||
/* NVRAM registers */
|
||||
struct eeprom_data *nvram;
|
||||
spinlock_t hardware_lock ____cacheline_aligned;
|
||||
spinlock_t list_lock;
|
||||
uint32_t eeprom_cmd_data;
|
||||
|
||||
/* Counters for general statistics */
|
||||
uint64_t isr_count;
|
||||
uint64_t adapter_error_count;
|
||||
uint64_t device_error_count;
|
||||
uint64_t total_io_count;
|
||||
uint64_t total_mbytes_xferred;
|
||||
uint64_t link_failure_count;
|
||||
uint64_t invalid_crc_count;
|
||||
uint32_t bytes_xfered;
|
||||
uint32_t spurious_int_count;
|
||||
uint32_t aborted_io_count;
|
||||
uint32_t io_timeout_count;
|
||||
@ -438,6 +442,11 @@ static inline int is_qla4022(struct scsi_qla_host *ha)
|
||||
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4022;
|
||||
}
|
||||
|
||||
static inline int is_qla4032(struct scsi_qla_host *ha)
|
||||
{
|
||||
return ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP4032;
|
||||
}
|
||||
|
||||
static inline int adapter_up(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (test_bit(AF_ONLINE, &ha->flags) != 0) &&
|
||||
@ -451,58 +460,58 @@ static inline struct scsi_qla_host* to_qla_host(struct Scsi_Host *shost)
|
||||
|
||||
static inline void __iomem* isp_semaphore(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (is_qla4022(ha) ?
|
||||
&ha->reg->u1.isp4022.semaphore :
|
||||
&ha->reg->u1.isp4010.nvram);
|
||||
return (is_qla4010(ha) ?
|
||||
&ha->reg->u1.isp4010.nvram :
|
||||
&ha->reg->u1.isp4022.semaphore);
|
||||
}
|
||||
|
||||
static inline void __iomem* isp_nvram(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (is_qla4022(ha) ?
|
||||
&ha->reg->u1.isp4022.nvram :
|
||||
&ha->reg->u1.isp4010.nvram);
|
||||
return (is_qla4010(ha) ?
|
||||
&ha->reg->u1.isp4010.nvram :
|
||||
&ha->reg->u1.isp4022.nvram);
|
||||
}
|
||||
|
||||
static inline void __iomem* isp_ext_hw_conf(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (is_qla4022(ha) ?
|
||||
&ha->reg->u2.isp4022.p0.ext_hw_conf :
|
||||
&ha->reg->u2.isp4010.ext_hw_conf);
|
||||
return (is_qla4010(ha) ?
|
||||
&ha->reg->u2.isp4010.ext_hw_conf :
|
||||
&ha->reg->u2.isp4022.p0.ext_hw_conf);
|
||||
}
|
||||
|
||||
static inline void __iomem* isp_port_status(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (is_qla4022(ha) ?
|
||||
&ha->reg->u2.isp4022.p0.port_status :
|
||||
&ha->reg->u2.isp4010.port_status);
|
||||
return (is_qla4010(ha) ?
|
||||
&ha->reg->u2.isp4010.port_status :
|
||||
&ha->reg->u2.isp4022.p0.port_status);
|
||||
}
|
||||
|
||||
static inline void __iomem* isp_port_ctrl(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (is_qla4022(ha) ?
|
||||
&ha->reg->u2.isp4022.p0.port_ctrl :
|
||||
&ha->reg->u2.isp4010.port_ctrl);
|
||||
return (is_qla4010(ha) ?
|
||||
&ha->reg->u2.isp4010.port_ctrl :
|
||||
&ha->reg->u2.isp4022.p0.port_ctrl);
|
||||
}
|
||||
|
||||
static inline void __iomem* isp_port_error_status(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (is_qla4022(ha) ?
|
||||
&ha->reg->u2.isp4022.p0.port_err_status :
|
||||
&ha->reg->u2.isp4010.port_err_status);
|
||||
return (is_qla4010(ha) ?
|
||||
&ha->reg->u2.isp4010.port_err_status :
|
||||
&ha->reg->u2.isp4022.p0.port_err_status);
|
||||
}
|
||||
|
||||
static inline void __iomem * isp_gp_out(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (is_qla4022(ha) ?
|
||||
&ha->reg->u2.isp4022.p0.gp_out :
|
||||
&ha->reg->u2.isp4010.gp_out);
|
||||
return (is_qla4010(ha) ?
|
||||
&ha->reg->u2.isp4010.gp_out :
|
||||
&ha->reg->u2.isp4022.p0.gp_out);
|
||||
}
|
||||
|
||||
static inline int eeprom_ext_hw_conf_offset(struct scsi_qla_host *ha)
|
||||
{
|
||||
return (is_qla4022(ha) ?
|
||||
offsetof(struct eeprom_data, isp4022.ext_hw_conf) / 2 :
|
||||
offsetof(struct eeprom_data, isp4010.ext_hw_conf) / 2);
|
||||
return (is_qla4010(ha) ?
|
||||
offsetof(struct eeprom_data, isp4010.ext_hw_conf) / 2 :
|
||||
offsetof(struct eeprom_data, isp4022.ext_hw_conf) / 2);
|
||||
}
|
||||
|
||||
int ql4xxx_sem_spinlock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits);
|
||||
@ -511,59 +520,59 @@ int ql4xxx_sem_lock(struct scsi_qla_host * ha, u32 sem_mask, u32 sem_bits);
|
||||
|
||||
static inline int ql4xxx_lock_flash(struct scsi_qla_host *a)
|
||||
{
|
||||
if (is_qla4022(a))
|
||||
if (is_qla4010(a))
|
||||
return ql4xxx_sem_spinlock(a, QL4010_FLASH_SEM_MASK,
|
||||
QL4010_FLASH_SEM_BITS);
|
||||
else
|
||||
return ql4xxx_sem_spinlock(a, QL4022_FLASH_SEM_MASK,
|
||||
(QL4022_RESOURCE_BITS_BASE_CODE |
|
||||
(a->mac_index)) << 13);
|
||||
else
|
||||
return ql4xxx_sem_spinlock(a, QL4010_FLASH_SEM_MASK,
|
||||
QL4010_FLASH_SEM_BITS);
|
||||
}
|
||||
|
||||
static inline void ql4xxx_unlock_flash(struct scsi_qla_host *a)
|
||||
{
|
||||
if (is_qla4022(a))
|
||||
ql4xxx_sem_unlock(a, QL4022_FLASH_SEM_MASK);
|
||||
else
|
||||
if (is_qla4010(a))
|
||||
ql4xxx_sem_unlock(a, QL4010_FLASH_SEM_MASK);
|
||||
else
|
||||
ql4xxx_sem_unlock(a, QL4022_FLASH_SEM_MASK);
|
||||
}
|
||||
|
||||
static inline int ql4xxx_lock_nvram(struct scsi_qla_host *a)
|
||||
{
|
||||
if (is_qla4022(a))
|
||||
if (is_qla4010(a))
|
||||
return ql4xxx_sem_spinlock(a, QL4010_NVRAM_SEM_MASK,
|
||||
QL4010_NVRAM_SEM_BITS);
|
||||
else
|
||||
return ql4xxx_sem_spinlock(a, QL4022_NVRAM_SEM_MASK,
|
||||
(QL4022_RESOURCE_BITS_BASE_CODE |
|
||||
(a->mac_index)) << 10);
|
||||
else
|
||||
return ql4xxx_sem_spinlock(a, QL4010_NVRAM_SEM_MASK,
|
||||
QL4010_NVRAM_SEM_BITS);
|
||||
}
|
||||
|
||||
static inline void ql4xxx_unlock_nvram(struct scsi_qla_host *a)
|
||||
{
|
||||
if (is_qla4022(a))
|
||||
ql4xxx_sem_unlock(a, QL4022_NVRAM_SEM_MASK);
|
||||
else
|
||||
if (is_qla4010(a))
|
||||
ql4xxx_sem_unlock(a, QL4010_NVRAM_SEM_MASK);
|
||||
else
|
||||
ql4xxx_sem_unlock(a, QL4022_NVRAM_SEM_MASK);
|
||||
}
|
||||
|
||||
static inline int ql4xxx_lock_drvr(struct scsi_qla_host *a)
|
||||
{
|
||||
if (is_qla4022(a))
|
||||
if (is_qla4010(a))
|
||||
return ql4xxx_sem_lock(a, QL4010_DRVR_SEM_MASK,
|
||||
QL4010_DRVR_SEM_BITS);
|
||||
else
|
||||
return ql4xxx_sem_lock(a, QL4022_DRVR_SEM_MASK,
|
||||
(QL4022_RESOURCE_BITS_BASE_CODE |
|
||||
(a->mac_index)) << 1);
|
||||
else
|
||||
return ql4xxx_sem_lock(a, QL4010_DRVR_SEM_MASK,
|
||||
QL4010_DRVR_SEM_BITS);
|
||||
}
|
||||
|
||||
static inline void ql4xxx_unlock_drvr(struct scsi_qla_host *a)
|
||||
{
|
||||
if (is_qla4022(a))
|
||||
ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK);
|
||||
else
|
||||
if (is_qla4010(a))
|
||||
ql4xxx_sem_unlock(a, QL4010_DRVR_SEM_MASK);
|
||||
else
|
||||
ql4xxx_sem_unlock(a, QL4022_DRVR_SEM_MASK);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
@ -296,7 +296,6 @@ static inline uint32_t clr_rmask(uint32_t val)
|
||||
/* ISP Semaphore definitions */
|
||||
|
||||
/* ISP General Purpose Output definitions */
|
||||
#define GPOR_TOPCAT_RESET 0x00000004
|
||||
|
||||
/* shadow registers (DMA'd from HA to system memory. read only) */
|
||||
struct shadow_regs {
|
||||
@ -339,10 +338,13 @@ union external_hw_config_reg {
|
||||
/* Mailbox command definitions */
|
||||
#define MBOX_CMD_ABOUT_FW 0x0009
|
||||
#define MBOX_CMD_LUN_RESET 0x0016
|
||||
#define MBOX_CMD_GET_MANAGEMENT_DATA 0x001E
|
||||
#define MBOX_CMD_GET_FW_STATUS 0x001F
|
||||
#define MBOX_CMD_SET_ISNS_SERVICE 0x0021
|
||||
#define ISNS_DISABLE 0
|
||||
#define ISNS_ENABLE 1
|
||||
#define MBOX_CMD_COPY_FLASH 0x0024
|
||||
#define MBOX_CMD_WRITE_FLASH 0x0025
|
||||
#define MBOX_CMD_READ_FLASH 0x0026
|
||||
#define MBOX_CMD_CLEAR_DATABASE_ENTRY 0x0031
|
||||
#define MBOX_CMD_CONN_CLOSE_SESS_LOGOUT 0x0056
|
||||
@ -360,10 +362,13 @@ union external_hw_config_reg {
|
||||
#define DDB_DS_SESSION_FAILED 0x06
|
||||
#define DDB_DS_LOGIN_IN_PROCESS 0x07
|
||||
#define MBOX_CMD_GET_FW_STATE 0x0069
|
||||
#define MBOX_CMD_GET_INIT_FW_CTRL_BLOCK_DEFAULTS 0x006A
|
||||
#define MBOX_CMD_RESTORE_FACTORY_DEFAULTS 0x0087
|
||||
|
||||
/* Mailbox 1 */
|
||||
#define FW_STATE_READY 0x0000
|
||||
#define FW_STATE_CONFIG_WAIT 0x0001
|
||||
#define FW_STATE_WAIT_LOGIN 0x0002
|
||||
#define FW_STATE_ERROR 0x0004
|
||||
#define FW_STATE_DHCP_IN_PROGRESS 0x0008
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#ifndef __QLA4x_GBL_H
|
||||
#define __QLA4x_GBL_H
|
||||
|
||||
int ql4xxx_lock_drvr_wait(struct scsi_qla_host *a);
|
||||
int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port);
|
||||
int qla4xxx_send_command_to_isp(struct scsi_qla_host *ha, struct srb * srb);
|
||||
int qla4xxx_initialize_adapter(struct scsi_qla_host * ha,
|
||||
@ -75,4 +76,4 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host * ha,
|
||||
extern int ql4xextended_error_logging;
|
||||
extern int ql4xdiscoverywait;
|
||||
extern int ql4xdontresethba;
|
||||
#endif /* _QLA4x_GBL_H */
|
||||
#endif /* _QLA4x_GBL_H */
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user