mirror of https://gitee.com/openkylin/linux.git
Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (58 commits) [SCSI] zfcp: clear boxed flag on unit reopen. [SCSI] zfcp: clear adapter failed flag if an fsf request times out. [SCSI] zfcp: rework request ID management. [SCSI] zfcp: Fix deadlock between zfcp ERP and SCSI [SCSI] zfcp: Locking for req_no and req_seq_no [SCSI] zfcp: print S_ID and D_ID with 3 bytes [SCSI] ipr: Use PCI-E reset API for new ipr adapter [SCSI] qla2xxx: Update version number to 8.01.07-k7. [SCSI] qla2xxx: Add MSI support. [SCSI] qla2xxx: Correct pci_set_msi() usage semantics. [SCSI] qla2xxx: Attempt to stop firmware only if it had been previously executed. [SCSI] qla2xxx: Honor NVRAM port-down-retry-count settings. [SCSI] qla2xxx: Error-out during probe() if we're unable to complete HBA initialization. [SCSI] zfcp: Stop system after memory corruption [SCSI] mesh: cleanup variable usage in interrupt handler [SCSI] megaraid: replace yield() with cond_resched() [SCSI] megaraid: fix warnings when CONFIG_PROC_FS=n [SCSI] aacraid: correct SUN products to README [SCSI] aacraid: superfluous adapter reset for IBM 8 series ServeRAID controllers [SCSI] aacraid: kexec fix (reset interrupt handler) ...
This commit is contained in:
commit
6ec129c3a2
|
@ -59,6 +59,15 @@ Who: Dan Dennedy <dan@dennedy.org>, Stefan Richter <stefanr@s5r6.in-berlin.de>
|
|||
|
||||
---------------------------
|
||||
|
||||
What: old NCR53C9x driver
|
||||
When: October 2007
|
||||
Why: Replaced by the much better esp_scsi driver. Actual low-level
|
||||
driver can ported over almost trivially.
|
||||
Who: David Miller <davem@davemloft.net>
|
||||
Christoph Hellwig <hch@lst.de>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: Video4Linux API 1 ioctls and video_decoder.h from Video devices.
|
||||
When: December 2006
|
||||
Why: V4L1 AP1 was replaced by V4L2 API. during migration from 2.4 to 2.6
|
||||
|
|
|
@ -98,8 +98,8 @@ Supported Cards/Chipsets
|
|||
9005:0285:9005:02b0 (Sunrise Lake ARK)
|
||||
9005:0285:9005:02b1 Adaptec (Voodoo 8 internal 8 external)
|
||||
9005:0285:108e:7aac SUN STK RAID REM (Voodoo44 Coyote)
|
||||
9005:0285:108e:0286 SUN SG-XPCIESAS-R-IN (Cougar)
|
||||
9005:0285:108e:0287 SUN SG-XPCIESAS-R-EX (Prometheus)
|
||||
9005:0285:108e:0286 SUN STK RAID INT (Cougar)
|
||||
9005:0285:108e:0287 SUN STK RAID EXT (Prometheus)
|
||||
|
||||
People
|
||||
-------------------------
|
||||
|
|
|
@ -118,97 +118,32 @@ _zfcp_hex_dump(char *addr, int count)
|
|||
|
||||
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_FSF
|
||||
|
||||
static int zfcp_reqlist_init(struct zfcp_adapter *adapter)
|
||||
static int zfcp_reqlist_alloc(struct zfcp_adapter *adapter)
|
||||
{
|
||||
int i;
|
||||
int idx;
|
||||
|
||||
adapter->req_list = kcalloc(REQUEST_LIST_SIZE, sizeof(struct list_head),
|
||||
GFP_KERNEL);
|
||||
|
||||
if (!adapter->req_list)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i=0; i<REQUEST_LIST_SIZE; i++)
|
||||
INIT_LIST_HEAD(&adapter->req_list[i]);
|
||||
|
||||
for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
|
||||
INIT_LIST_HEAD(&adapter->req_list[idx]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void zfcp_reqlist_free(struct zfcp_adapter *adapter)
|
||||
{
|
||||
struct zfcp_fsf_req *request, *tmp;
|
||||
unsigned int i;
|
||||
|
||||
for (i=0; i<REQUEST_LIST_SIZE; i++) {
|
||||
if (list_empty(&adapter->req_list[i]))
|
||||
continue;
|
||||
|
||||
list_for_each_entry_safe(request, tmp,
|
||||
&adapter->req_list[i], list)
|
||||
list_del(&request->list);
|
||||
}
|
||||
|
||||
kfree(adapter->req_list);
|
||||
}
|
||||
|
||||
void zfcp_reqlist_add(struct zfcp_adapter *adapter,
|
||||
struct zfcp_fsf_req *fsf_req)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
i = fsf_req->req_id % REQUEST_LIST_SIZE;
|
||||
list_add_tail(&fsf_req->list, &adapter->req_list[i]);
|
||||
}
|
||||
|
||||
void zfcp_reqlist_remove(struct zfcp_adapter *adapter, unsigned long req_id)
|
||||
{
|
||||
struct zfcp_fsf_req *request, *tmp;
|
||||
unsigned int i, counter;
|
||||
u64 dbg_tmp[2];
|
||||
|
||||
i = req_id % REQUEST_LIST_SIZE;
|
||||
BUG_ON(list_empty(&adapter->req_list[i]));
|
||||
|
||||
counter = 0;
|
||||
list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list) {
|
||||
if (request->req_id == req_id) {
|
||||
dbg_tmp[0] = (u64) atomic_read(&adapter->reqs_active);
|
||||
dbg_tmp[1] = (u64) counter;
|
||||
debug_event(adapter->erp_dbf, 4, (void *) dbg_tmp, 16);
|
||||
list_del(&request->list);
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *adapter,
|
||||
unsigned long req_id)
|
||||
{
|
||||
struct zfcp_fsf_req *request, *tmp;
|
||||
unsigned int i;
|
||||
|
||||
/* 0 is reserved as an invalid req_id */
|
||||
if (req_id == 0)
|
||||
return NULL;
|
||||
|
||||
i = req_id % REQUEST_LIST_SIZE;
|
||||
|
||||
list_for_each_entry_safe(request, tmp, &adapter->req_list[i], list)
|
||||
if (request->req_id == req_id)
|
||||
return request;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int zfcp_reqlist_isempty(struct zfcp_adapter *adapter)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int idx;
|
||||
|
||||
for (i=0; i<REQUEST_LIST_SIZE; i++)
|
||||
if (!list_empty(&adapter->req_list[i]))
|
||||
for (idx = 0; idx < REQUEST_LIST_SIZE; idx++)
|
||||
if (!list_empty(&adapter->req_list[idx]))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -913,6 +848,8 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
|
|||
unit->sysfs_device.release = zfcp_sysfs_unit_release;
|
||||
dev_set_drvdata(&unit->sysfs_device, unit);
|
||||
|
||||
init_waitqueue_head(&unit->scsi_scan_wq);
|
||||
|
||||
/* mark unit unusable as long as sysfs registration is not complete */
|
||||
atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
|
||||
|
||||
|
@ -1104,7 +1041,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
|
|||
|
||||
/* initialize list of fsf requests */
|
||||
spin_lock_init(&adapter->req_list_lock);
|
||||
retval = zfcp_reqlist_init(adapter);
|
||||
retval = zfcp_reqlist_alloc(adapter);
|
||||
if (retval) {
|
||||
ZFCP_LOG_INFO("request list initialization failed\n");
|
||||
goto failed_low_mem_buffers;
|
||||
|
@ -1165,6 +1102,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
|
|||
zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
|
||||
sysfs_failed:
|
||||
dev_set_drvdata(&ccw_device->dev, NULL);
|
||||
zfcp_reqlist_free(adapter);
|
||||
failed_low_mem_buffers:
|
||||
zfcp_free_low_mem_buffers(adapter);
|
||||
if (qdio_free(ccw_device) != 0)
|
||||
|
@ -1497,7 +1435,7 @@ zfcp_fsf_incoming_els_plogi(struct zfcp_adapter *adapter,
|
|||
|
||||
if (!port || (port->wwpn != (*(wwn_t *) &els_plogi->serv_param.wwpn))) {
|
||||
ZFCP_LOG_DEBUG("ignored incoming PLOGI for nonexisting port "
|
||||
"with d_id 0x%08x on adapter %s\n",
|
||||
"with d_id 0x%06x on adapter %s\n",
|
||||
status_buffer->d_id,
|
||||
zfcp_get_busid_by_adapter(adapter));
|
||||
} else {
|
||||
|
@ -1522,7 +1460,7 @@ zfcp_fsf_incoming_els_logo(struct zfcp_adapter *adapter,
|
|||
|
||||
if (!port || (port->wwpn != els_logo->nport_wwpn)) {
|
||||
ZFCP_LOG_DEBUG("ignored incoming LOGO for nonexisting port "
|
||||
"with d_id 0x%08x on adapter %s\n",
|
||||
"with d_id 0x%06x on adapter %s\n",
|
||||
status_buffer->d_id,
|
||||
zfcp_get_busid_by_adapter(adapter));
|
||||
} else {
|
||||
|
@ -1704,7 +1642,7 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
|
|||
/* looks like a valid d_id */
|
||||
port->d_id = ct_iu_resp->d_id & ZFCP_DID_MASK;
|
||||
atomic_set_mask(ZFCP_STATUS_PORT_DID_DID, &port->status);
|
||||
ZFCP_LOG_DEBUG("adapter %s: wwpn=0x%016Lx ---> d_id=0x%08x\n",
|
||||
ZFCP_LOG_DEBUG("adapter %s: wwpn=0x%016Lx ---> d_id=0x%06x\n",
|
||||
zfcp_get_busid_by_port(port), port->wwpn, port->d_id);
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -637,6 +637,7 @@ do { \
|
|||
#define ZFCP_STATUS_UNIT_SHARED 0x00000004
|
||||
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
|
||||
#define ZFCP_STATUS_UNIT_REGISTERED 0x00000010
|
||||
#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
|
||||
|
||||
/* FSF request status (this does not have a common part) */
|
||||
#define ZFCP_STATUS_FSFREQ_NOT_INIT 0x00000000
|
||||
|
@ -980,6 +981,10 @@ struct zfcp_unit {
|
|||
struct scsi_device *device; /* scsi device struct pointer */
|
||||
struct zfcp_erp_action erp_action; /* pending error recovery */
|
||||
atomic_t erp_counter;
|
||||
wait_queue_head_t scsi_scan_wq; /* can be used to wait until
|
||||
all scsi_scan_target
|
||||
requests have been
|
||||
completed. */
|
||||
};
|
||||
|
||||
/* FSF request */
|
||||
|
@ -1084,6 +1089,42 @@ extern void _zfcp_hex_dump(char *, int);
|
|||
#define zfcp_get_busid_by_port(port) (zfcp_get_busid_by_adapter(port->adapter))
|
||||
#define zfcp_get_busid_by_unit(unit) (zfcp_get_busid_by_port(unit->port))
|
||||
|
||||
/*
|
||||
* Helper functions for request ID management.
|
||||
*/
|
||||
static inline int zfcp_reqlist_hash(unsigned long req_id)
|
||||
{
|
||||
return req_id % REQUEST_LIST_SIZE;
|
||||
}
|
||||
|
||||
static inline void zfcp_reqlist_add(struct zfcp_adapter *adapter,
|
||||
struct zfcp_fsf_req *fsf_req)
|
||||
{
|
||||
unsigned int idx;
|
||||
|
||||
idx = zfcp_reqlist_hash(fsf_req->req_id);
|
||||
list_add_tail(&fsf_req->list, &adapter->req_list[idx]);
|
||||
}
|
||||
|
||||
static inline void zfcp_reqlist_remove(struct zfcp_adapter *adapter,
|
||||
struct zfcp_fsf_req *fsf_req)
|
||||
{
|
||||
list_del(&fsf_req->list);
|
||||
}
|
||||
|
||||
static inline struct zfcp_fsf_req *
|
||||
zfcp_reqlist_find(struct zfcp_adapter *adapter, unsigned long req_id)
|
||||
{
|
||||
struct zfcp_fsf_req *request;
|
||||
unsigned int idx;
|
||||
|
||||
idx = zfcp_reqlist_hash(req_id);
|
||||
list_for_each_entry(request, &adapter->req_list[idx], list)
|
||||
if (request->req_id == req_id)
|
||||
return request;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* functions needed for reference/usage counting
|
||||
*/
|
||||
|
|
|
@ -179,7 +179,7 @@ static void zfcp_close_fsf(struct zfcp_adapter *adapter)
|
|||
static void zfcp_fsf_request_timeout_handler(unsigned long data)
|
||||
{
|
||||
struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
|
||||
zfcp_erp_adapter_reopen(adapter, 0);
|
||||
zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED);
|
||||
}
|
||||
|
||||
void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout)
|
||||
|
@ -342,9 +342,9 @@ zfcp_erp_adisc(struct zfcp_port *port)
|
|||
adisc->wwpn = fc_host_port_name(adapter->scsi_host);
|
||||
adisc->wwnn = fc_host_node_name(adapter->scsi_host);
|
||||
adisc->nport_id = fc_host_port_id(adapter->scsi_host);
|
||||
ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
|
||||
ZFCP_LOG_INFO("ADISC request from s_id 0x%06x to d_id 0x%06x "
|
||||
"(wwpn=0x%016Lx, wwnn=0x%016Lx, "
|
||||
"hard_nport_id=0x%08x, nport_id=0x%08x)\n",
|
||||
"hard_nport_id=0x%06x, nport_id=0x%06x)\n",
|
||||
adisc->nport_id, send_els->d_id, (wwn_t) adisc->wwpn,
|
||||
(wwn_t) adisc->wwnn, adisc->hard_nport_id,
|
||||
adisc->nport_id);
|
||||
|
@ -352,7 +352,7 @@ zfcp_erp_adisc(struct zfcp_port *port)
|
|||
retval = zfcp_fsf_send_els(send_els);
|
||||
if (retval != 0) {
|
||||
ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
|
||||
"0x%08x on adapter %s\n", send_els->d_id,
|
||||
"0x%06x on adapter %s\n", send_els->d_id,
|
||||
zfcp_get_busid_by_adapter(adapter));
|
||||
goto freemem;
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ zfcp_erp_adisc_handler(unsigned long data)
|
|||
if (send_els->status != 0) {
|
||||
ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
|
||||
"force physical port reopen "
|
||||
"(adapter %s, port d_id=0x%08x)\n",
|
||||
"(adapter %s, port d_id=0x%06x)\n",
|
||||
zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
debug_text_event(adapter->erp_dbf, 3, "forcreop");
|
||||
if (zfcp_erp_port_forced_reopen(port, 0))
|
||||
|
@ -411,9 +411,9 @@ zfcp_erp_adisc_handler(unsigned long data)
|
|||
|
||||
adisc = zfcp_sg_to_address(send_els->resp);
|
||||
|
||||
ZFCP_LOG_INFO("ADISC response from d_id 0x%08x to s_id "
|
||||
"0x%08x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
|
||||
"hard_nport_id=0x%08x, nport_id=0x%08x)\n",
|
||||
ZFCP_LOG_INFO("ADISC response from d_id 0x%06x to s_id "
|
||||
"0x%06x (wwpn=0x%016Lx, wwnn=0x%016Lx, "
|
||||
"hard_nport_id=0x%06x, nport_id=0x%06x)\n",
|
||||
d_id, fc_host_port_id(adapter->scsi_host),
|
||||
(wwn_t) adisc->wwpn, (wwn_t) adisc->wwnn,
|
||||
adisc->hard_nport_id, adisc->nport_id);
|
||||
|
@ -847,8 +847,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
|
|||
if (erp_action->fsf_req) {
|
||||
/* take lock to ensure that request is not deleted meanwhile */
|
||||
spin_lock(&adapter->req_list_lock);
|
||||
if (zfcp_reqlist_ismember(adapter,
|
||||
erp_action->fsf_req->req_id)) {
|
||||
if (zfcp_reqlist_find(adapter, erp_action->fsf_req->req_id)) {
|
||||
/* fsf_req still exists */
|
||||
debug_text_event(adapter->erp_dbf, 3, "a_ca_req");
|
||||
debug_event(adapter->erp_dbf, 3, &erp_action->fsf_req,
|
||||
|
@ -1377,7 +1376,7 @@ zfcp_erp_port_failed(struct zfcp_port *port)
|
|||
|
||||
if (atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
|
||||
ZFCP_LOG_NORMAL("port erp failed (adapter %s, "
|
||||
"port d_id=0x%08x)\n",
|
||||
"port d_id=0x%06x)\n",
|
||||
zfcp_get_busid_by_port(port), port->d_id);
|
||||
else
|
||||
ZFCP_LOG_NORMAL("port erp failed (adapter %s, wwpn=0x%016Lx)\n",
|
||||
|
@ -1591,6 +1590,62 @@ zfcp_erp_strategy_check_adapter(struct zfcp_adapter *adapter, int result)
|
|||
return result;
|
||||
}
|
||||
|
||||
struct zfcp_erp_add_work {
|
||||
struct zfcp_unit *unit;
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
/**
|
||||
* zfcp_erp_scsi_scan
|
||||
* @data: pointer to a struct zfcp_erp_add_work
|
||||
*
|
||||
* Registers a logical unit with the SCSI stack.
|
||||
*/
|
||||
static void zfcp_erp_scsi_scan(struct work_struct *work)
|
||||
{
|
||||
struct zfcp_erp_add_work *p =
|
||||
container_of(work, struct zfcp_erp_add_work, work);
|
||||
struct zfcp_unit *unit = p->unit;
|
||||
struct fc_rport *rport = unit->port->rport;
|
||||
scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
|
||||
unit->scsi_lun, 0);
|
||||
atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
|
||||
wake_up(&unit->scsi_scan_wq);
|
||||
zfcp_unit_put(unit);
|
||||
kfree(p);
|
||||
}
|
||||
|
||||
/**
|
||||
* zfcp_erp_schedule_work
|
||||
* @unit: pointer to unit which should be registered with SCSI stack
|
||||
*
|
||||
* Schedules work which registers a unit with the SCSI stack
|
||||
*/
|
||||
static void
|
||||
zfcp_erp_schedule_work(struct zfcp_unit *unit)
|
||||
{
|
||||
struct zfcp_erp_add_work *p;
|
||||
|
||||
p = kmalloc(sizeof(*p), GFP_KERNEL);
|
||||
if (!p) {
|
||||
ZFCP_LOG_NORMAL("error: Out of resources. Could not register "
|
||||
"the FCP-LUN 0x%Lx connected to "
|
||||
"the port with WWPN 0x%Lx connected to "
|
||||
"the adapter %s with the SCSI stack.\n",
|
||||
unit->fcp_lun,
|
||||
unit->port->wwpn,
|
||||
zfcp_get_busid_by_unit(unit));
|
||||
return;
|
||||
}
|
||||
|
||||
zfcp_unit_get(unit);
|
||||
memset(p, 0, sizeof(*p));
|
||||
atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
|
||||
INIT_WORK(&p->work, zfcp_erp_scsi_scan);
|
||||
p->unit = unit;
|
||||
schedule_work(&p->work);
|
||||
}
|
||||
|
||||
/*
|
||||
* function:
|
||||
*
|
||||
|
@ -2401,7 +2456,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
|
|||
retval = ZFCP_ERP_FAILED;
|
||||
}
|
||||
} else {
|
||||
ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%08x -> "
|
||||
ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> "
|
||||
"trying open\n", port->wwpn, port->d_id);
|
||||
retval = zfcp_erp_port_strategy_open_port(erp_action);
|
||||
}
|
||||
|
@ -2441,7 +2496,7 @@ zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action)
|
|||
case ZFCP_ERP_STEP_UNINITIALIZED:
|
||||
case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
|
||||
case ZFCP_ERP_STEP_PORT_CLOSING:
|
||||
ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%08x -> trying open\n",
|
||||
ZFCP_LOG_DEBUG("port 0x%016Lx has d_id=0x%06x -> trying open\n",
|
||||
port->wwpn, port->d_id);
|
||||
retval = zfcp_erp_port_strategy_open_port(erp_action);
|
||||
break;
|
||||
|
@ -3092,9 +3147,9 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
|
|||
&& port->rport) {
|
||||
atomic_set_mask(ZFCP_STATUS_UNIT_REGISTERED,
|
||||
&unit->status);
|
||||
scsi_scan_target(&port->rport->dev, 0,
|
||||
port->rport->scsi_target_id,
|
||||
unit->scsi_lun, 0);
|
||||
if (atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
|
||||
&unit->status) == 0)
|
||||
zfcp_erp_schedule_work(unit);
|
||||
}
|
||||
zfcp_unit_put(unit);
|
||||
break;
|
||||
|
@ -3121,7 +3176,7 @@ zfcp_erp_action_cleanup(int action, struct zfcp_adapter *adapter,
|
|||
zfcp_get_busid_by_port(port),
|
||||
port->wwpn);
|
||||
else {
|
||||
scsi_flush_work(adapter->scsi_host);
|
||||
scsi_target_unblock(&port->rport->dev);
|
||||
port->rport->maxframe_size = port->maxframe_size;
|
||||
port->rport->supported_classes =
|
||||
port->supported_classes;
|
||||
|
|
|
@ -184,10 +184,6 @@ extern void zfcp_scsi_dbf_event_abort(const char *, struct zfcp_adapter *,
|
|||
unsigned long);
|
||||
extern void zfcp_scsi_dbf_event_devreset(const char *, u8, struct zfcp_unit *,
|
||||
struct scsi_cmnd *);
|
||||
extern void zfcp_reqlist_add(struct zfcp_adapter *, struct zfcp_fsf_req *);
|
||||
extern void zfcp_reqlist_remove(struct zfcp_adapter *, unsigned long);
|
||||
extern struct zfcp_fsf_req *zfcp_reqlist_ismember(struct zfcp_adapter *,
|
||||
unsigned long);
|
||||
extern int zfcp_reqlist_isempty(struct zfcp_adapter *);
|
||||
|
||||
#endif /* ZFCP_EXT_H */
|
||||
|
|
|
@ -828,7 +828,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
|
|||
|
||||
if (!port || (port->d_id != (status_buffer->d_id & ZFCP_DID_MASK))) {
|
||||
ZFCP_LOG_NORMAL("bug: Reopen port indication received for"
|
||||
"nonexisting port with d_id 0x%08x on "
|
||||
"nonexisting port with d_id 0x%06x on "
|
||||
"adapter %s. Ignored.\n",
|
||||
status_buffer->d_id & ZFCP_DID_MASK,
|
||||
zfcp_get_busid_by_adapter(adapter));
|
||||
|
@ -853,7 +853,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req)
|
|||
&status_buffer->status_subtype, sizeof (u32));
|
||||
ZFCP_LOG_NORMAL("bug: Undefined status subtype received "
|
||||
"for a reopen indication on port with "
|
||||
"d_id 0x%08x on the adapter %s. "
|
||||
"d_id 0x%06x on the adapter %s. "
|
||||
"Ignored. (debug info 0x%x)\n",
|
||||
status_buffer->d_id,
|
||||
zfcp_get_busid_by_adapter(adapter),
|
||||
|
@ -1156,7 +1156,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id,
|
|||
}
|
||||
|
||||
ZFCP_LOG_DEBUG("Abort FCP Command request initiated "
|
||||
"(adapter%s, port d_id=0x%08x, "
|
||||
"(adapter%s, port d_id=0x%06x, "
|
||||
"unit x%016Lx, old_req_id=0x%lx)\n",
|
||||
zfcp_get_busid_by_adapter(adapter),
|
||||
unit->port->d_id,
|
||||
|
@ -1554,7 +1554,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
|
|||
|
||||
case FSF_ACCESS_DENIED:
|
||||
ZFCP_LOG_NORMAL("access denied, cannot send generic service "
|
||||
"command (adapter %s, port d_id=0x%08x)\n",
|
||||
"command (adapter %s, port d_id=0x%06x)\n",
|
||||
zfcp_get_busid_by_port(port), port->d_id);
|
||||
for (counter = 0; counter < 2; counter++) {
|
||||
subtable = header->fsf_status_qual.halfword[counter * 2];
|
||||
|
@ -1576,7 +1576,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
|
|||
|
||||
case FSF_GENERIC_COMMAND_REJECTED:
|
||||
ZFCP_LOG_INFO("generic service command rejected "
|
||||
"(adapter %s, port d_id=0x%08x)\n",
|
||||
"(adapter %s, port d_id=0x%06x)\n",
|
||||
zfcp_get_busid_by_port(port), port->d_id);
|
||||
ZFCP_LOG_INFO("status qualifier:\n");
|
||||
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_INFO,
|
||||
|
@ -1602,7 +1602,7 @@ zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *fsf_req)
|
|||
|
||||
case FSF_PORT_BOXED:
|
||||
ZFCP_LOG_INFO("port needs to be reopened "
|
||||
"(adapter %s, port d_id=0x%08x)\n",
|
||||
"(adapter %s, port d_id=0x%06x)\n",
|
||||
zfcp_get_busid_by_port(port), port->d_id);
|
||||
debug_text_event(adapter->erp_dbf, 2, "fsf_s_pboxed");
|
||||
zfcp_erp_port_boxed(port);
|
||||
|
@ -1683,7 +1683,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
|
|||
NULL, &lock_flags, &fsf_req);
|
||||
if (ret < 0) {
|
||||
ZFCP_LOG_INFO("error: creation of ELS request failed "
|
||||
"(adapter %s, port d_id: 0x%08x)\n",
|
||||
"(adapter %s, port d_id: 0x%06x)\n",
|
||||
zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
goto failed_req;
|
||||
}
|
||||
|
@ -1708,7 +1708,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
|
|||
ZFCP_MAX_SBALS_PER_ELS_REQ);
|
||||
if (bytes <= 0) {
|
||||
ZFCP_LOG_INFO("error: creation of ELS request failed "
|
||||
"(adapter %s, port d_id: 0x%08x)\n",
|
||||
"(adapter %s, port d_id: 0x%06x)\n",
|
||||
zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
if (bytes == 0) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -1725,7 +1725,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
|
|||
ZFCP_MAX_SBALS_PER_ELS_REQ);
|
||||
if (bytes <= 0) {
|
||||
ZFCP_LOG_INFO("error: creation of ELS request failed "
|
||||
"(adapter %s, port d_id: 0x%08x)\n",
|
||||
"(adapter %s, port d_id: 0x%06x)\n",
|
||||
zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
if (bytes == 0) {
|
||||
ret = -ENOMEM;
|
||||
|
@ -1739,7 +1739,7 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
|
|||
/* reject request */
|
||||
ZFCP_LOG_INFO("error: microcode does not support chained SBALs"
|
||||
", ELS request too big (adapter %s, "
|
||||
"port d_id: 0x%08x)\n",
|
||||
"port d_id: 0x%06x)\n",
|
||||
zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
ret = -EOPNOTSUPP;
|
||||
goto failed_send;
|
||||
|
@ -1760,13 +1760,13 @@ zfcp_fsf_send_els(struct zfcp_send_els *els)
|
|||
ret = zfcp_fsf_req_send(fsf_req);
|
||||
if (ret) {
|
||||
ZFCP_LOG_DEBUG("error: initiation of ELS request failed "
|
||||
"(adapter %s, port d_id: 0x%08x)\n",
|
||||
"(adapter %s, port d_id: 0x%06x)\n",
|
||||
zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
goto failed_send;
|
||||
}
|
||||
|
||||
ZFCP_LOG_DEBUG("ELS request initiated (adapter %s, port d_id: "
|
||||
"0x%08x)\n", zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
"0x%06x)\n", zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
goto out;
|
||||
|
||||
failed_send:
|
||||
|
@ -1859,7 +1859,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
|
|||
case FSF_ELS_COMMAND_REJECTED:
|
||||
ZFCP_LOG_INFO("ELS has been rejected because command filter "
|
||||
"prohibited sending "
|
||||
"(adapter: %s, port d_id: 0x%08x)\n",
|
||||
"(adapter: %s, port d_id: 0x%06x)\n",
|
||||
zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
|
||||
break;
|
||||
|
@ -1907,7 +1907,7 @@ static int zfcp_fsf_send_els_handler(struct zfcp_fsf_req *fsf_req)
|
|||
|
||||
case FSF_ACCESS_DENIED:
|
||||
ZFCP_LOG_NORMAL("access denied, cannot send ELS command "
|
||||
"(adapter %s, port d_id=0x%08x)\n",
|
||||
"(adapter %s, port d_id=0x%06x)\n",
|
||||
zfcp_get_busid_by_adapter(adapter), d_id);
|
||||
for (counter = 0; counter < 2; counter++) {
|
||||
subtable = header->fsf_status_qual.halfword[counter * 2];
|
||||
|
@ -2070,7 +2070,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
|
|||
ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n"
|
||||
"WWNN 0x%016Lx, "
|
||||
"WWPN 0x%016Lx, "
|
||||
"S_ID 0x%08x,\n"
|
||||
"S_ID 0x%06x,\n"
|
||||
"adapter version 0x%x, "
|
||||
"LIC version 0x%x, "
|
||||
"FC link speed %d Gb/s\n",
|
||||
|
@ -3043,6 +3043,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req)
|
|||
queue_designator = &header->fsf_status_qual.fsf_queue_designator;
|
||||
|
||||
atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED |
|
||||
ZFCP_STATUS_COMMON_ACCESS_BOXED |
|
||||
ZFCP_STATUS_UNIT_SHARED |
|
||||
ZFCP_STATUS_UNIT_READONLY,
|
||||
&unit->status);
|
||||
|
@ -4645,23 +4646,22 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags,
|
|||
fsf_req->adapter = adapter;
|
||||
fsf_req->fsf_command = fsf_cmd;
|
||||
INIT_LIST_HEAD(&fsf_req->list);
|
||||
|
||||
/* this is serialized (we are holding req_queue-lock of adapter */
|
||||
if (adapter->req_no == 0)
|
||||
adapter->req_no++;
|
||||
fsf_req->req_id = adapter->req_no++;
|
||||
|
||||
init_timer(&fsf_req->timer);
|
||||
zfcp_fsf_req_qtcb_init(fsf_req);
|
||||
|
||||
/* initialize waitqueue which may be used to wait on
|
||||
this request completion */
|
||||
init_waitqueue_head(&fsf_req->completion_wq);
|
||||
|
||||
ret = zfcp_fsf_req_sbal_get(adapter, req_flags, lock_flags);
|
||||
if(ret < 0) {
|
||||
if (ret < 0)
|
||||
goto failed_sbals;
|
||||
}
|
||||
|
||||
/* this is serialized (we are holding req_queue-lock of adapter) */
|
||||
if (adapter->req_no == 0)
|
||||
adapter->req_no++;
|
||||
fsf_req->req_id = adapter->req_no++;
|
||||
|
||||
zfcp_fsf_req_qtcb_init(fsf_req);
|
||||
|
||||
/*
|
||||
* We hold queue_lock here. Check if QDIOUP is set and let request fail
|
||||
|
@ -4788,7 +4788,7 @@ static int zfcp_fsf_req_send(struct zfcp_fsf_req *fsf_req)
|
|||
retval = -EIO;
|
||||
del_timer(&fsf_req->timer);
|
||||
spin_lock(&adapter->req_list_lock);
|
||||
zfcp_reqlist_remove(adapter, fsf_req->req_id);
|
||||
zfcp_reqlist_remove(adapter, fsf_req);
|
||||
spin_unlock(&adapter->req_list_lock);
|
||||
/* undo changes in request queue made for this request */
|
||||
zfcp_qdio_zero_sbals(req_queue->buffer,
|
||||
|
|
|
@ -283,10 +283,10 @@ zfcp_qdio_request_handler(struct ccw_device *ccw_device,
|
|||
}
|
||||
|
||||
/**
|
||||
* zfcp_qdio_reqid_check - checks for valid reqids or unsolicited status
|
||||
* zfcp_qdio_reqid_check - checks for valid reqids.
|
||||
*/
|
||||
static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
|
||||
unsigned long req_id)
|
||||
static void zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
|
||||
unsigned long req_id)
|
||||
{
|
||||
struct zfcp_fsf_req *fsf_req;
|
||||
unsigned long flags;
|
||||
|
@ -294,23 +294,22 @@ static int zfcp_qdio_reqid_check(struct zfcp_adapter *adapter,
|
|||
debug_long_event(adapter->erp_dbf, 4, req_id);
|
||||
|
||||
spin_lock_irqsave(&adapter->req_list_lock, flags);
|
||||
fsf_req = zfcp_reqlist_ismember(adapter, req_id);
|
||||
fsf_req = zfcp_reqlist_find(adapter, req_id);
|
||||
|
||||
if (!fsf_req) {
|
||||
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
|
||||
ZFCP_LOG_NORMAL("error: unknown request id (%ld).\n", req_id);
|
||||
zfcp_erp_adapter_reopen(adapter, 0);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!fsf_req)
|
||||
/*
|
||||
* Unknown request means that we have potentially memory
|
||||
* corruption and must stop the machine immediatly.
|
||||
*/
|
||||
panic("error: unknown request id (%ld) on adapter %s.\n",
|
||||
req_id, zfcp_get_busid_by_adapter(adapter));
|
||||
|
||||
zfcp_reqlist_remove(adapter, req_id);
|
||||
zfcp_reqlist_remove(adapter, fsf_req);
|
||||
atomic_dec(&adapter->reqs_active);
|
||||
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
|
||||
|
||||
/* finish the FSF request */
|
||||
zfcp_fsf_req_complete(fsf_req);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -374,27 +373,9 @@ zfcp_qdio_response_handler(struct ccw_device *ccw_device,
|
|||
|
||||
/* look for QDIO request identifiers in SB */
|
||||
buffere = &buffer->element[buffere_index];
|
||||
retval = zfcp_qdio_reqid_check(adapter,
|
||||
(unsigned long) buffere->addr);
|
||||
zfcp_qdio_reqid_check(adapter,
|
||||
(unsigned long) buffere->addr);
|
||||
|
||||
if (retval) {
|
||||
ZFCP_LOG_NORMAL("bug: unexpected inbound "
|
||||
"packet on adapter %s "
|
||||
"(reqid=0x%lx, "
|
||||
"first_element=%d, "
|
||||
"elements_processed=%d)\n",
|
||||
zfcp_get_busid_by_adapter(adapter),
|
||||
(unsigned long) buffere->addr,
|
||||
first_element,
|
||||
elements_processed);
|
||||
ZFCP_LOG_NORMAL("hex dump of inbound buffer "
|
||||
"at address %p "
|
||||
"(buffer_index=%d, "
|
||||
"buffere_index=%d)\n", buffer,
|
||||
buffer_index, buffere_index);
|
||||
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_NORMAL,
|
||||
(char *) buffer, SBAL_SIZE);
|
||||
}
|
||||
/*
|
||||
* A single used SBALE per inbound SBALE has been
|
||||
* implemented by QDIO so far. Hope they will
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI
|
||||
|
||||
#include "zfcp_ext.h"
|
||||
#include <asm/atomic.h>
|
||||
|
||||
static void zfcp_scsi_slave_destroy(struct scsi_device *sdp);
|
||||
static int zfcp_scsi_slave_alloc(struct scsi_device *sdp);
|
||||
|
@ -179,6 +180,10 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt)
|
|||
struct zfcp_unit *unit = (struct zfcp_unit *) sdpnt->hostdata;
|
||||
|
||||
if (unit) {
|
||||
zfcp_erp_wait(unit->port->adapter);
|
||||
wait_event(unit->scsi_scan_wq,
|
||||
atomic_test_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING,
|
||||
&unit->status) == 0);
|
||||
atomic_clear_mask(ZFCP_STATUS_UNIT_REGISTERED, &unit->status);
|
||||
sdpnt->hostdata = NULL;
|
||||
unit->device = NULL;
|
||||
|
@ -402,8 +407,8 @@ static int zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
|
|||
|
||||
/* Check whether corresponding fsf_req is still pending */
|
||||
spin_lock(&adapter->req_list_lock);
|
||||
fsf_req = zfcp_reqlist_ismember(adapter, (unsigned long)
|
||||
scpnt->host_scribble);
|
||||
fsf_req = zfcp_reqlist_find(adapter,
|
||||
(unsigned long) scpnt->host_scribble);
|
||||
spin_unlock(&adapter->req_list_lock);
|
||||
if (!fsf_req) {
|
||||
write_unlock_irqrestore(&adapter->abort_lock, flags);
|
||||
|
|
|
@ -387,12 +387,11 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
|||
* Ok now init the communication subsystem
|
||||
*/
|
||||
|
||||
dev->queues = kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
|
||||
dev->queues = kzalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
|
||||
if (dev->queues == NULL) {
|
||||
printk(KERN_ERR "Error could not allocate comm region.\n");
|
||||
return NULL;
|
||||
}
|
||||
memset(dev->queues, 0, sizeof(struct aac_queue_block));
|
||||
|
||||
if (aac_comm_init(dev)<0){
|
||||
kfree(dev->queues);
|
||||
|
|
|
@ -1223,13 +1223,11 @@ int aac_check_health(struct aac_dev * aac)
|
|||
* Warning: no sleep allowed while
|
||||
* holding spinlock
|
||||
*/
|
||||
hw_fib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC);
|
||||
fib = kmalloc(sizeof(struct fib), GFP_ATOMIC);
|
||||
hw_fib = kzalloc(sizeof(struct hw_fib), GFP_ATOMIC);
|
||||
fib = kzalloc(sizeof(struct fib), GFP_ATOMIC);
|
||||
if (fib && hw_fib) {
|
||||
struct aac_aifcmd * aif;
|
||||
|
||||
memset(hw_fib, 0, sizeof(struct hw_fib));
|
||||
memset(fib, 0, sizeof(struct fib));
|
||||
fib->hw_fib_va = hw_fib;
|
||||
fib->dev = aac;
|
||||
aac_fib_init(fib);
|
||||
|
|
|
@ -248,16 +248,14 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
|
|||
* manage the linked lists.
|
||||
*/
|
||||
if ((!dev->aif_thread)
|
||||
|| (!(fib = kmalloc(sizeof(struct fib),GFP_ATOMIC))))
|
||||
|| (!(fib = kzalloc(sizeof(struct fib),GFP_ATOMIC))))
|
||||
return 1;
|
||||
if (!(hw_fib = kmalloc(sizeof(struct hw_fib),GFP_ATOMIC))) {
|
||||
if (!(hw_fib = kzalloc(sizeof(struct hw_fib),GFP_ATOMIC))) {
|
||||
kfree (fib);
|
||||
return 1;
|
||||
}
|
||||
memset(hw_fib, 0, sizeof(struct hw_fib));
|
||||
memcpy(hw_fib, (struct hw_fib *)(((ptrdiff_t)(dev->regs.sa)) +
|
||||
(index & ~0x00000002L)), sizeof(struct hw_fib));
|
||||
memset(fib, 0, sizeof(struct fib));
|
||||
INIT_LIST_HEAD(&fib->fiblink);
|
||||
fib->type = FSAFS_NTC_FIB_CONTEXT;
|
||||
fib->size = sizeof(struct fib);
|
||||
|
|
|
@ -539,8 +539,10 @@ int _aac_rx_init(struct aac_dev *dev)
|
|||
}
|
||||
|
||||
/* Failure to reset here is an option ... */
|
||||
dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
|
||||
dev->a_ops.adapter_enable_int = aac_rx_disable_interrupt;
|
||||
dev->OIMR = status = rx_readb (dev, MUnit.OIMR);
|
||||
if ((((status & 0xff) != 0xff) || reset_devices) &&
|
||||
if ((((status & 0x0c) != 0x0c) || reset_devices) &&
|
||||
!aac_rx_restart_adapter(dev, 0))
|
||||
++restart;
|
||||
/*
|
||||
|
|
|
@ -319,10 +319,9 @@ ch_readconfig(scsi_changer *ch)
|
|||
int result,id,lun,i;
|
||||
u_int elem;
|
||||
|
||||
buffer = kmalloc(512, GFP_KERNEL | GFP_DMA);
|
||||
buffer = kzalloc(512, GFP_KERNEL | GFP_DMA);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
memset(buffer,0,512);
|
||||
|
||||
memset(cmd,0,sizeof(cmd));
|
||||
cmd[0] = MODE_SENSE;
|
||||
|
@ -530,10 +529,9 @@ ch_set_voltag(scsi_changer *ch, u_int elem,
|
|||
u_char *buffer;
|
||||
int result;
|
||||
|
||||
buffer = kmalloc(512, GFP_KERNEL);
|
||||
buffer = kzalloc(512, GFP_KERNEL);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
memset(buffer,0,512);
|
||||
|
||||
dprintk("%s %s voltag: 0x%x => \"%s\"\n",
|
||||
clear ? "clear" : "set",
|
||||
|
@ -922,11 +920,10 @@ static int ch_probe(struct device *dev)
|
|||
if (sd->type != TYPE_MEDIUM_CHANGER)
|
||||
return -ENODEV;
|
||||
|
||||
ch = kmalloc(sizeof(*ch), GFP_KERNEL);
|
||||
ch = kzalloc(sizeof(*ch), GFP_KERNEL);
|
||||
if (NULL == ch)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(ch,0,sizeof(*ch));
|
||||
ch->minor = ch_devcount;
|
||||
sprintf(ch->name,"ch%d",ch->minor);
|
||||
mutex_init(&ch->lock);
|
||||
|
|
|
@ -1308,13 +1308,12 @@ static s32 adpt_i2o_reset_hba(adpt_hba* pHba)
|
|||
schedule_timeout_uninterruptible(1);
|
||||
} while (m == EMPTY_QUEUE);
|
||||
|
||||
status = kmalloc(4, GFP_KERNEL|ADDR32);
|
||||
status = kzalloc(4, GFP_KERNEL|ADDR32);
|
||||
if(status == NULL) {
|
||||
adpt_send_nop(pHba, m);
|
||||
printk(KERN_ERR"IOP reset failed - no free memory.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(status,0,4);
|
||||
|
||||
msg[0]=EIGHT_WORD_MSG_SIZE|SGL_OFFSET_0;
|
||||
msg[1]=I2O_CMD_ADAPTER_RESET<<24|HOST_TID<<12|ADAPTER_TID;
|
||||
|
@ -1504,21 +1503,19 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba)
|
|||
continue;
|
||||
}
|
||||
if( pHba->channel[bus_no].device[scsi_id] == NULL){
|
||||
pDev = kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
|
||||
pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
|
||||
if(pDev == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
pHba->channel[bus_no].device[scsi_id] = pDev;
|
||||
memset(pDev,0,sizeof(struct adpt_device));
|
||||
} else {
|
||||
for( pDev = pHba->channel[bus_no].device[scsi_id];
|
||||
pDev->next_lun; pDev = pDev->next_lun){
|
||||
}
|
||||
pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
|
||||
pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
|
||||
if(pDev->next_lun == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(pDev->next_lun,0,sizeof(struct adpt_device));
|
||||
pDev = pDev->next_lun;
|
||||
}
|
||||
pDev->tid = tid;
|
||||
|
@ -1667,12 +1664,11 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
|
|||
reply_size = REPLY_FRAME_SIZE;
|
||||
}
|
||||
reply_size *= 4;
|
||||
reply = kmalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
|
||||
reply = kzalloc(REPLY_FRAME_SIZE*4, GFP_KERNEL);
|
||||
if(reply == NULL) {
|
||||
printk(KERN_WARNING"%s: Could not allocate reply buffer\n",pHba->name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(reply,0,REPLY_FRAME_SIZE*4);
|
||||
sg_offset = (msg[0]>>4)&0xf;
|
||||
msg[2] = 0x40000000; // IOCTL context
|
||||
msg[3] = (u32)reply;
|
||||
|
@ -2444,7 +2440,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
|
|||
}
|
||||
pDev = pHba->channel[bus_no].device[scsi_id];
|
||||
if( pDev == NULL){
|
||||
pDev = kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
|
||||
pDev = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
|
||||
if(pDev == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -2453,12 +2449,11 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba)
|
|||
while (pDev->next_lun) {
|
||||
pDev = pDev->next_lun;
|
||||
}
|
||||
pDev = pDev->next_lun = kmalloc(sizeof(struct adpt_device),GFP_KERNEL);
|
||||
pDev = pDev->next_lun = kzalloc(sizeof(struct adpt_device),GFP_KERNEL);
|
||||
if(pDev == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
memset(pDev,0,sizeof(struct adpt_device));
|
||||
pDev->tid = d->lct_data.tid;
|
||||
pDev->scsi_channel = bus_no;
|
||||
pDev->scsi_id = scsi_id;
|
||||
|
|
|
@ -92,6 +92,7 @@ static unsigned int ipr_fastfail = 0;
|
|||
static unsigned int ipr_transop_timeout = 0;
|
||||
static unsigned int ipr_enable_cache = 1;
|
||||
static unsigned int ipr_debug = 0;
|
||||
static unsigned int ipr_dual_ioa_raid = 1;
|
||||
static DEFINE_SPINLOCK(ipr_driver_lock);
|
||||
|
||||
/* This table describes the differences between DMA controller chips */
|
||||
|
@ -158,6 +159,8 @@ module_param_named(enable_cache, ipr_enable_cache, int, 0);
|
|||
MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
|
||||
module_param_named(debug, ipr_debug, int, 0);
|
||||
MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
|
||||
module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0);
|
||||
MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_VERSION(IPR_DRIVER_VERSION);
|
||||
|
||||
|
@ -206,6 +209,8 @@ struct ipr_error_table_t ipr_error_table[] = {
|
|||
"8009: Impending cache battery pack failure"},
|
||||
{0x02040400, 0, 0,
|
||||
"34FF: Disk device format in progress"},
|
||||
{0x02048000, 0, IPR_DEFAULT_LOG_LEVEL,
|
||||
"9070: IOA requested reset"},
|
||||
{0x023F0000, 0, 0,
|
||||
"Synchronization required"},
|
||||
{0x024E0000, 0, 0,
|
||||
|
@ -950,6 +955,53 @@ static void ipr_process_ccn(struct ipr_cmnd *ipr_cmd)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* strip_and_pad_whitespace - Strip and pad trailing whitespace.
|
||||
* @i: index into buffer
|
||||
* @buf: string to modify
|
||||
*
|
||||
* This function will strip all trailing whitespace, pad the end
|
||||
* of the string with a single space, and NULL terminate the string.
|
||||
*
|
||||
* Return value:
|
||||
* new length of string
|
||||
**/
|
||||
static int strip_and_pad_whitespace(int i, char *buf)
|
||||
{
|
||||
while (i && buf[i] == ' ')
|
||||
i--;
|
||||
buf[i+1] = ' ';
|
||||
buf[i+2] = '\0';
|
||||
return i + 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_log_vpd_compact - Log the passed extended VPD compactly.
|
||||
* @prefix: string to print at start of printk
|
||||
* @hostrcb: hostrcb pointer
|
||||
* @vpd: vendor/product id/sn struct
|
||||
*
|
||||
* Return value:
|
||||
* none
|
||||
**/
|
||||
static void ipr_log_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb,
|
||||
struct ipr_vpd *vpd)
|
||||
{
|
||||
char buffer[IPR_VENDOR_ID_LEN + IPR_PROD_ID_LEN + IPR_SERIAL_NUM_LEN + 3];
|
||||
int i = 0;
|
||||
|
||||
memcpy(buffer, vpd->vpids.vendor_id, IPR_VENDOR_ID_LEN);
|
||||
i = strip_and_pad_whitespace(IPR_VENDOR_ID_LEN - 1, buffer);
|
||||
|
||||
memcpy(&buffer[i], vpd->vpids.product_id, IPR_PROD_ID_LEN);
|
||||
i = strip_and_pad_whitespace(i + IPR_PROD_ID_LEN - 1, buffer);
|
||||
|
||||
memcpy(&buffer[i], vpd->sn, IPR_SERIAL_NUM_LEN);
|
||||
buffer[IPR_SERIAL_NUM_LEN + i] = '\0';
|
||||
|
||||
ipr_hcam_err(hostrcb, "%s VPID/SN: %s\n", prefix, buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_log_vpd - Log the passed VPD to the error log.
|
||||
* @vpd: vendor/product id/sn struct
|
||||
|
@ -973,6 +1025,23 @@ static void ipr_log_vpd(struct ipr_vpd *vpd)
|
|||
ipr_err(" Serial Number: %s\n", buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_log_ext_vpd_compact - Log the passed extended VPD compactly.
|
||||
* @prefix: string to print at start of printk
|
||||
* @hostrcb: hostrcb pointer
|
||||
* @vpd: vendor/product id/sn/wwn struct
|
||||
*
|
||||
* Return value:
|
||||
* none
|
||||
**/
|
||||
static void ipr_log_ext_vpd_compact(char *prefix, struct ipr_hostrcb *hostrcb,
|
||||
struct ipr_ext_vpd *vpd)
|
||||
{
|
||||
ipr_log_vpd_compact(prefix, hostrcb, &vpd->vpd);
|
||||
ipr_hcam_err(hostrcb, "%s WWN: %08X%08X\n", prefix,
|
||||
be32_to_cpu(vpd->wwid[0]), be32_to_cpu(vpd->wwid[1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_log_ext_vpd - Log the passed extended VPD to the error log.
|
||||
* @vpd: vendor/product id/sn/wwn struct
|
||||
|
@ -1287,10 +1356,11 @@ static void ipr_log_enhanced_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
|
|||
|
||||
error = &hostrcb->hcam.u.error.u.type_17_error;
|
||||
error->failure_reason[sizeof(error->failure_reason) - 1] = '\0';
|
||||
strstrip(error->failure_reason);
|
||||
|
||||
ipr_err("%s\n", error->failure_reason);
|
||||
ipr_err("Remote Adapter VPD:\n");
|
||||
ipr_log_ext_vpd(&error->vpd);
|
||||
ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason,
|
||||
be32_to_cpu(hostrcb->hcam.u.error.prc));
|
||||
ipr_log_ext_vpd_compact("Remote IOA", hostrcb, &error->vpd);
|
||||
ipr_log_hex_data(ioa_cfg, error->data,
|
||||
be32_to_cpu(hostrcb->hcam.length) -
|
||||
(offsetof(struct ipr_hostrcb_error, u) +
|
||||
|
@ -1312,10 +1382,11 @@ static void ipr_log_dual_ioa_error(struct ipr_ioa_cfg *ioa_cfg,
|
|||
|
||||
error = &hostrcb->hcam.u.error.u.type_07_error;
|
||||
error->failure_reason[sizeof(error->failure_reason) - 1] = '\0';
|
||||
strstrip(error->failure_reason);
|
||||
|
||||
ipr_err("%s\n", error->failure_reason);
|
||||
ipr_err("Remote Adapter VPD:\n");
|
||||
ipr_log_vpd(&error->vpd);
|
||||
ipr_hcam_err(hostrcb, "%s [PRC: %08X]\n", error->failure_reason,
|
||||
be32_to_cpu(hostrcb->hcam.u.error.prc));
|
||||
ipr_log_vpd_compact("Remote IOA", hostrcb, &error->vpd);
|
||||
ipr_log_hex_data(ioa_cfg, error->data,
|
||||
be32_to_cpu(hostrcb->hcam.length) -
|
||||
(offsetof(struct ipr_hostrcb_error, u) +
|
||||
|
@ -1672,12 +1743,15 @@ static void ipr_process_error(struct ipr_cmnd *ipr_cmd)
|
|||
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
|
||||
struct ipr_hostrcb *hostrcb = ipr_cmd->u.hostrcb;
|
||||
u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
|
||||
u32 fd_ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc);
|
||||
|
||||
list_del(&hostrcb->queue);
|
||||
list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q);
|
||||
|
||||
if (!ioasc) {
|
||||
ipr_handle_log_data(ioa_cfg, hostrcb);
|
||||
if (fd_ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED)
|
||||
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_ABBREV);
|
||||
} else if (ioasc != IPR_IOASC_IOA_WAS_RESET) {
|
||||
dev_err(&ioa_cfg->pdev->dev,
|
||||
"Host RCB failed with IOASC: 0x%08X\n", ioasc);
|
||||
|
@ -2635,8 +2709,13 @@ static ssize_t ipr_store_diagnostics(struct class_device *class_dev,
|
|||
if (!capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
|
||||
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
|
||||
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);
|
||||
}
|
||||
|
||||
ioa_cfg->errors_logged = 0;
|
||||
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NORMAL);
|
||||
|
||||
|
@ -2958,6 +3037,11 @@ static int ipr_update_ioa_ucode(struct ipr_ioa_cfg *ioa_cfg,
|
|||
unsigned long lock_flags;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
if (ioa_cfg->ucode_sglist) {
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
|
@ -4656,18 +4740,19 @@ static void ipr_erp_start(struct ipr_ioa_cfg *ioa_cfg,
|
|||
struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd;
|
||||
struct ipr_resource_entry *res = scsi_cmd->device->hostdata;
|
||||
u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
|
||||
u32 masked_ioasc = ioasc & IPR_IOASC_IOASC_MASK;
|
||||
|
||||
if (!res) {
|
||||
ipr_scsi_eh_done(ipr_cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ipr_is_gscsi(res))
|
||||
if (!ipr_is_gscsi(res) && masked_ioasc != IPR_IOASC_HW_DEV_BUS_STATUS)
|
||||
ipr_gen_sense(ipr_cmd);
|
||||
|
||||
ipr_dump_ioasa(ioa_cfg, ipr_cmd, res);
|
||||
|
||||
switch (ioasc & IPR_IOASC_IOASC_MASK) {
|
||||
switch (masked_ioasc) {
|
||||
case IPR_IOASC_ABORTED_CMD_TERM_BY_HOST:
|
||||
if (ipr_is_naca_model(res))
|
||||
scsi_cmd->result |= (DID_ABORT << 16);
|
||||
|
@ -5363,6 +5448,7 @@ static int ipr_ioa_reset_done(struct ipr_cmnd *ipr_cmd)
|
|||
ipr_send_hcam(ioa_cfg, IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE, hostrcb);
|
||||
}
|
||||
|
||||
scsi_report_bus_reset(ioa_cfg->host, IPR_VSET_BUS);
|
||||
dev_info(&ioa_cfg->pdev->dev, "IOA initialized.\n");
|
||||
|
||||
ioa_cfg->reset_retries = 0;
|
||||
|
@ -5798,6 +5884,94 @@ static int ipr_ioafp_mode_sense_page28(struct ipr_cmnd *ipr_cmd)
|
|||
return IPR_RC_JOB_RETURN;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_ioafp_mode_select_page24 - Issue Mode Select to IOA
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function enables dual IOA RAID support if possible.
|
||||
*
|
||||
* Return value:
|
||||
* IPR_RC_JOB_RETURN
|
||||
**/
|
||||
static int ipr_ioafp_mode_select_page24(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
|
||||
struct ipr_mode_pages *mode_pages = &ioa_cfg->vpd_cbs->mode_pages;
|
||||
struct ipr_mode_page24 *mode_page;
|
||||
int length;
|
||||
|
||||
ENTER;
|
||||
mode_page = ipr_get_mode_page(mode_pages, 0x24,
|
||||
sizeof(struct ipr_mode_page24));
|
||||
|
||||
if (mode_page)
|
||||
mode_page->flags |= IPR_ENABLE_DUAL_IOA_AF;
|
||||
|
||||
length = mode_pages->hdr.length + 1;
|
||||
mode_pages->hdr.length = 0;
|
||||
|
||||
ipr_build_mode_select(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE), 0x11,
|
||||
ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, mode_pages),
|
||||
length);
|
||||
|
||||
ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
|
||||
ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT);
|
||||
|
||||
LEAVE;
|
||||
return IPR_RC_JOB_RETURN;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_reset_mode_sense_page24_failed - Handle failure of IOAFP mode sense
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function handles the failure of a Mode Sense to the IOAFP.
|
||||
* Some adapters do not handle all mode pages.
|
||||
*
|
||||
* Return value:
|
||||
* IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
|
||||
**/
|
||||
static int ipr_reset_mode_sense_page24_failed(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
u32 ioasc = be32_to_cpu(ipr_cmd->ioasa.ioasc);
|
||||
|
||||
if (ioasc == IPR_IOASC_IR_INVALID_REQ_TYPE_OR_PKT) {
|
||||
ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
|
||||
return IPR_RC_JOB_CONTINUE;
|
||||
}
|
||||
|
||||
return ipr_reset_cmd_failed(ipr_cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_ioafp_mode_sense_page24 - Issue Page 24 Mode Sense to IOA
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function send a mode sense to the IOA to retrieve
|
||||
* the IOA Advanced Function Control mode page.
|
||||
*
|
||||
* Return value:
|
||||
* IPR_RC_JOB_RETURN
|
||||
**/
|
||||
static int ipr_ioafp_mode_sense_page24(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
|
||||
|
||||
ENTER;
|
||||
ipr_build_mode_sense(ipr_cmd, cpu_to_be32(IPR_IOA_RES_HANDLE),
|
||||
0x24, ioa_cfg->vpd_cbs_dma +
|
||||
offsetof(struct ipr_misc_cbs, mode_pages),
|
||||
sizeof(struct ipr_mode_pages));
|
||||
|
||||
ipr_cmd->job_step = ipr_ioafp_mode_select_page24;
|
||||
ipr_cmd->job_step_failed = ipr_reset_mode_sense_page24_failed;
|
||||
|
||||
ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, IPR_INTERNAL_TIMEOUT);
|
||||
|
||||
LEAVE;
|
||||
return IPR_RC_JOB_RETURN;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_init_res_table - Initialize the resource table
|
||||
* @ipr_cmd: ipr command struct
|
||||
|
@ -5866,7 +6040,10 @@ static int ipr_init_res_table(struct ipr_cmnd *ipr_cmd)
|
|||
}
|
||||
}
|
||||
|
||||
ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
|
||||
if (ioa_cfg->dual_raid && ipr_dual_ioa_raid)
|
||||
ipr_cmd->job_step = ipr_ioafp_mode_sense_page24;
|
||||
else
|
||||
ipr_cmd->job_step = ipr_ioafp_mode_sense_page28;
|
||||
|
||||
LEAVE;
|
||||
return IPR_RC_JOB_CONTINUE;
|
||||
|
@ -5888,8 +6065,11 @@ static int ipr_ioafp_query_ioa_cfg(struct ipr_cmnd *ipr_cmd)
|
|||
struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb;
|
||||
struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl;
|
||||
struct ipr_inquiry_page3 *ucode_vpd = &ioa_cfg->vpd_cbs->page3_data;
|
||||
struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap;
|
||||
|
||||
ENTER;
|
||||
if (cap->cap & IPR_CAP_DUAL_IOA_RAID)
|
||||
ioa_cfg->dual_raid = 1;
|
||||
dev_info(&ioa_cfg->pdev->dev, "Adapter firmware version: %02X%02X%02X%02X\n",
|
||||
ucode_vpd->major_release, ucode_vpd->card_type,
|
||||
ucode_vpd->minor_release[0], ucode_vpd->minor_release[1]);
|
||||
|
@ -5972,6 +6152,37 @@ static int ipr_inquiry_page_supported(struct ipr_inquiry_page0 *page0, u8 page)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_ioafp_cap_inquiry - Send a Page 0xD0 Inquiry to the adapter.
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* This function sends a Page 0xD0 inquiry to the adapter
|
||||
* to retrieve adapter capabilities.
|
||||
*
|
||||
* Return value:
|
||||
* IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
|
||||
**/
|
||||
static int ipr_ioafp_cap_inquiry(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
|
||||
struct ipr_inquiry_page0 *page0 = &ioa_cfg->vpd_cbs->page0_data;
|
||||
struct ipr_inquiry_cap *cap = &ioa_cfg->vpd_cbs->cap;
|
||||
|
||||
ENTER;
|
||||
ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg;
|
||||
memset(cap, 0, sizeof(*cap));
|
||||
|
||||
if (ipr_inquiry_page_supported(page0, 0xD0)) {
|
||||
ipr_ioafp_inquiry(ipr_cmd, 1, 0xD0,
|
||||
ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, cap),
|
||||
sizeof(struct ipr_inquiry_cap));
|
||||
return IPR_RC_JOB_RETURN;
|
||||
}
|
||||
|
||||
LEAVE;
|
||||
return IPR_RC_JOB_CONTINUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_ioafp_page3_inquiry - Send a Page 3 Inquiry to the adapter.
|
||||
* @ipr_cmd: ipr command struct
|
||||
|
@ -5992,7 +6203,7 @@ static int ipr_ioafp_page3_inquiry(struct ipr_cmnd *ipr_cmd)
|
|||
if (!ipr_inquiry_page_supported(page0, 1))
|
||||
ioa_cfg->cache_state = CACHE_NONE;
|
||||
|
||||
ipr_cmd->job_step = ipr_ioafp_query_ioa_cfg;
|
||||
ipr_cmd->job_step = ipr_ioafp_cap_inquiry;
|
||||
|
||||
ipr_ioafp_inquiry(ipr_cmd, 1, 3,
|
||||
ioa_cfg->vpd_cbs_dma + offsetof(struct ipr_misc_cbs, page3_data),
|
||||
|
@ -6278,6 +6489,7 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
|
|||
struct ipr_hostrcb *hostrcb;
|
||||
struct ipr_uc_sdt sdt;
|
||||
int rc, length;
|
||||
u32 ioasc;
|
||||
|
||||
mailbox = readl(ioa_cfg->ioa_mailbox);
|
||||
|
||||
|
@ -6310,9 +6522,13 @@ static void ipr_get_unit_check_buffer(struct ipr_ioa_cfg *ioa_cfg)
|
|||
(__be32 *)&hostrcb->hcam,
|
||||
min(length, (int)sizeof(hostrcb->hcam)) / sizeof(__be32));
|
||||
|
||||
if (!rc)
|
||||
if (!rc) {
|
||||
ipr_handle_log_data(ioa_cfg, hostrcb);
|
||||
else
|
||||
ioasc = be32_to_cpu(hostrcb->hcam.u.error.failing_dev_ioasc);
|
||||
if (ioasc == IPR_IOASC_NR_IOA_RESET_REQUIRED &&
|
||||
ioa_cfg->sdt_state == GET_DUMP)
|
||||
ioa_cfg->sdt_state = WAIT_FOR_DUMP;
|
||||
} else
|
||||
ipr_unit_check_no_data(ioa_cfg);
|
||||
|
||||
list_add_tail(&hostrcb->queue, &ioa_cfg->hostrcb_free_q);
|
||||
|
@ -6424,6 +6640,48 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_reset_slot_reset_done - Clear PCI reset to the adapter
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* Description: This clears PCI reset to the adapter and delays two seconds.
|
||||
*
|
||||
* Return value:
|
||||
* IPR_RC_JOB_RETURN
|
||||
**/
|
||||
static int ipr_reset_slot_reset_done(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
ENTER;
|
||||
pci_set_pcie_reset_state(ipr_cmd->ioa_cfg->pdev, pcie_deassert_reset);
|
||||
ipr_cmd->job_step = ipr_reset_bist_done;
|
||||
ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
|
||||
LEAVE;
|
||||
return IPR_RC_JOB_RETURN;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_reset_slot_reset - Reset the PCI slot of the adapter.
|
||||
* @ipr_cmd: ipr command struct
|
||||
*
|
||||
* Description: This asserts PCI reset to the adapter.
|
||||
*
|
||||
* Return value:
|
||||
* IPR_RC_JOB_RETURN
|
||||
**/
|
||||
static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
|
||||
{
|
||||
struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
|
||||
struct pci_dev *pdev = ioa_cfg->pdev;
|
||||
|
||||
ENTER;
|
||||
pci_block_user_cfg_access(pdev);
|
||||
pci_set_pcie_reset_state(pdev, pcie_warm_reset);
|
||||
ipr_cmd->job_step = ipr_reset_slot_reset_done;
|
||||
ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT);
|
||||
LEAVE;
|
||||
return IPR_RC_JOB_RETURN;
|
||||
}
|
||||
|
||||
/**
|
||||
* ipr_reset_allowed - Query whether or not IOA can be reset
|
||||
* @ioa_cfg: ioa config struct
|
||||
|
@ -6463,7 +6721,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd)
|
|||
ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
|
||||
ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT);
|
||||
} else {
|
||||
ipr_cmd->job_step = ipr_reset_start_bist;
|
||||
ipr_cmd->job_step = ioa_cfg->reset;
|
||||
rc = IPR_RC_JOB_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -6496,7 +6754,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd)
|
|||
writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg);
|
||||
ipr_cmd->job_step = ipr_reset_wait_to_start_bist;
|
||||
} else {
|
||||
ipr_cmd->job_step = ipr_reset_start_bist;
|
||||
ipr_cmd->job_step = ioa_cfg->reset;
|
||||
}
|
||||
|
||||
ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
|
||||
|
@ -6591,12 +6849,14 @@ static int ipr_reset_shutdown_ioa(struct ipr_cmnd *ipr_cmd)
|
|||
ipr_cmd->ioarcb.cmd_pkt.cdb[0] = IPR_IOA_SHUTDOWN;
|
||||
ipr_cmd->ioarcb.cmd_pkt.cdb[1] = shutdown_type;
|
||||
|
||||
if (shutdown_type == IPR_SHUTDOWN_ABBREV)
|
||||
timeout = IPR_ABBREV_SHUTDOWN_TIMEOUT;
|
||||
if (shutdown_type == IPR_SHUTDOWN_NORMAL)
|
||||
timeout = IPR_SHUTDOWN_TIMEOUT;
|
||||
else if (shutdown_type == IPR_SHUTDOWN_PREPARE_FOR_NORMAL)
|
||||
timeout = IPR_INTERNAL_TIMEOUT;
|
||||
else if (ioa_cfg->dual_raid && ipr_dual_ioa_raid)
|
||||
timeout = IPR_DUAL_IOA_ABBR_SHUTDOWN_TO;
|
||||
else
|
||||
timeout = IPR_SHUTDOWN_TIMEOUT;
|
||||
timeout = IPR_ABBREV_SHUTDOWN_TIMEOUT;
|
||||
|
||||
ipr_do_req(ipr_cmd, ipr_reset_ioa_job, ipr_timeout, timeout);
|
||||
|
||||
|
@ -6776,8 +7036,11 @@ static pci_ers_result_t ipr_pci_slot_reset(struct pci_dev *pdev)
|
|||
struct ipr_ioa_cfg *ioa_cfg = pci_get_drvdata(pdev);
|
||||
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, flags);
|
||||
_ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space,
|
||||
IPR_SHUTDOWN_NONE);
|
||||
if (ioa_cfg->needs_warm_reset)
|
||||
ipr_initiate_ioa_reset(ioa_cfg, IPR_SHUTDOWN_NONE);
|
||||
else
|
||||
_ipr_initiate_ioa_reset(ioa_cfg, ipr_reset_restore_cfg_space,
|
||||
IPR_SHUTDOWN_NONE);
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags);
|
||||
return PCI_ERS_RESULT_RECOVERED;
|
||||
}
|
||||
|
@ -7226,7 +7489,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
|
|||
unsigned long ipr_regs_pci;
|
||||
void __iomem *ipr_regs;
|
||||
int rc = PCIBIOS_SUCCESSFUL;
|
||||
volatile u32 mask, uproc;
|
||||
volatile u32 mask, uproc, interrupts;
|
||||
|
||||
ENTER;
|
||||
|
||||
|
@ -7265,6 +7528,14 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
|
|||
else
|
||||
ioa_cfg->transop_timeout = IPR_OPERATIONAL_TIMEOUT;
|
||||
|
||||
rc = pci_read_config_byte(pdev, PCI_REVISION_ID, &ioa_cfg->revid);
|
||||
|
||||
if (rc != PCIBIOS_SUCCESSFUL) {
|
||||
dev_err(&pdev->dev, "Failed to read PCI revision ID\n");
|
||||
rc = -EIO;
|
||||
goto out_scsi_host_put;
|
||||
}
|
||||
|
||||
ipr_regs_pci = pci_resource_start(pdev, 0);
|
||||
|
||||
rc = pci_request_regions(pdev, IPR_NAME);
|
||||
|
@ -7333,9 +7604,14 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
|
|||
* the card is in an unknown state and needs a hard reset
|
||||
*/
|
||||
mask = readl(ioa_cfg->regs.sense_interrupt_mask_reg);
|
||||
interrupts = readl(ioa_cfg->regs.sense_interrupt_reg);
|
||||
uproc = readl(ioa_cfg->regs.sense_uproc_interrupt_reg);
|
||||
if ((mask & IPR_PCII_HRRQ_UPDATED) == 0 || (uproc & IPR_UPROCI_RESET_ALERT))
|
||||
ioa_cfg->needs_hard_reset = 1;
|
||||
if (interrupts & IPR_PCII_ERROR_INTERRUPTS)
|
||||
ioa_cfg->needs_hard_reset = 1;
|
||||
if (interrupts & IPR_PCII_IOA_UNIT_CHECKED)
|
||||
ioa_cfg->ioa_unit_checked = 1;
|
||||
|
||||
ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER);
|
||||
rc = request_irq(pdev->irq, ipr_isr, IRQF_SHARED, IPR_NAME, ioa_cfg);
|
||||
|
@ -7346,6 +7622,13 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
|
|||
goto cleanup_nolog;
|
||||
}
|
||||
|
||||
if ((dev_id->driver_data & IPR_USE_PCI_WARM_RESET) ||
|
||||
(dev_id->device == PCI_DEVICE_ID_IBM_OBSIDIAN_E && !ioa_cfg->revid)) {
|
||||
ioa_cfg->needs_warm_reset = 1;
|
||||
ioa_cfg->reset = ipr_reset_slot_reset;
|
||||
} else
|
||||
ioa_cfg->reset = ipr_reset_start_bist;
|
||||
|
||||
spin_lock(&ipr_driver_lock);
|
||||
list_add_tail(&ioa_cfg->queue, &ipr_ioa_head);
|
||||
spin_unlock(&ipr_driver_lock);
|
||||
|
@ -7428,6 +7711,12 @@ static void __ipr_remove(struct pci_dev *pdev)
|
|||
ENTER;
|
||||
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
|
||||
while(ioa_cfg->in_reset_reload) {
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
|
||||
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
|
||||
spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
|
||||
}
|
||||
|
||||
ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL);
|
||||
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
|
||||
|
@ -7551,6 +7840,12 @@ static void ipr_shutdown(struct pci_dev *pdev)
|
|||
unsigned long lock_flags = 0;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
ipr_initiate_ioa_bringdown(ioa_cfg, IPR_SHUTDOWN_NORMAL);
|
||||
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
|
||||
wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
|
||||
|
@ -7577,19 +7872,22 @@ 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_572A, 0, 0, 0 },
|
||||
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0,
|
||||
IPR_USE_LONG_TRANSOP_TIMEOUT },
|
||||
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
|
||||
IPR_USE_LONG_TRANSOP_TIMEOUT },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572A, 0, 0, 0 },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0, 0 },
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_572B, 0, 0,
|
||||
IPR_USE_LONG_TRANSOP_TIMEOUT},
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575C, 0, 0,
|
||||
IPR_USE_LONG_TRANSOP_TIMEOUT },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0, 0 },
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_574E, 0, 0,
|
||||
IPR_USE_LONG_TRANSOP_TIMEOUT },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_575D, 0, 0,
|
||||
IPR_USE_LONG_TRANSOP_TIMEOUT },
|
||||
|
@ -7597,7 +7895,7 @@ static struct pci_device_id ipr_pci_table[] __devinitdata = {
|
|||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B3, 0, 0, 0 },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_57B7, 0, 0,
|
||||
IPR_USE_LONG_TRANSOP_TIMEOUT },
|
||||
IPR_USE_LONG_TRANSOP_TIMEOUT | IPR_USE_PCI_WARM_RESET },
|
||||
{ PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE,
|
||||
PCI_VENDOR_ID_IBM, IPR_SUBS_DEV_ID_2780, 0, 0, 0 },
|
||||
{ PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP,
|
||||
|
@ -7627,6 +7925,7 @@ static struct pci_driver ipr_driver = {
|
|||
.remove = ipr_remove,
|
||||
.shutdown = ipr_shutdown,
|
||||
.err_handler = &ipr_err_handler,
|
||||
.dynids.use_driver_data = 1
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -37,8 +37,8 @@
|
|||
/*
|
||||
* Literals
|
||||
*/
|
||||
#define IPR_DRIVER_VERSION "2.3.2"
|
||||
#define IPR_DRIVER_DATE "(March 23, 2007)"
|
||||
#define IPR_DRIVER_VERSION "2.4.1"
|
||||
#define IPR_DRIVER_DATE "(April 24, 2007)"
|
||||
|
||||
/*
|
||||
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
|
||||
|
@ -91,6 +91,7 @@
|
|||
* IOASCs
|
||||
*/
|
||||
#define IPR_IOASC_NR_INIT_CMD_REQUIRED 0x02040200
|
||||
#define IPR_IOASC_NR_IOA_RESET_REQUIRED 0x02048000
|
||||
#define IPR_IOASC_SYNC_REQUIRED 0x023f0000
|
||||
#define IPR_IOASC_MED_DO_NOT_REALLOC 0x03110C00
|
||||
#define IPR_IOASC_HW_SEL_TIMEOUT 0x04050000
|
||||
|
@ -111,6 +112,7 @@
|
|||
|
||||
/* Driver data flags */
|
||||
#define IPR_USE_LONG_TRANSOP_TIMEOUT 0x00000001
|
||||
#define IPR_USE_PCI_WARM_RESET 0x00000002
|
||||
|
||||
#define IPR_DEFAULT_MAX_ERROR_DUMP 984
|
||||
#define IPR_NUM_LOG_HCAMS 2
|
||||
|
@ -179,6 +181,7 @@
|
|||
#define IPR_SHUTDOWN_TIMEOUT (ipr_fastfail ? 60 * HZ : 10 * 60 * HZ)
|
||||
#define IPR_VSET_RW_TIMEOUT (ipr_fastfail ? 30 * HZ : 2 * 60 * HZ)
|
||||
#define IPR_ABBREV_SHUTDOWN_TIMEOUT (10 * HZ)
|
||||
#define IPR_DUAL_IOA_ABBR_SHUTDOWN_TO (2 * 60 * HZ)
|
||||
#define IPR_DEVICE_RESET_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
|
||||
#define IPR_CANCEL_ALL_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
|
||||
#define IPR_ABORT_TASK_TIMEOUT (ipr_fastfail ? 10 * HZ : 30 * HZ)
|
||||
|
@ -191,6 +194,7 @@
|
|||
#define IPR_WAIT_FOR_RESET_TIMEOUT (2 * HZ)
|
||||
#define IPR_CHECK_FOR_RESET_TIMEOUT (HZ / 10)
|
||||
#define IPR_WAIT_FOR_BIST_TIMEOUT (2 * HZ)
|
||||
#define IPR_PCI_RESET_TIMEOUT (HZ / 2)
|
||||
#define IPR_DUMP_TIMEOUT (15 * HZ)
|
||||
|
||||
/*
|
||||
|
@ -602,6 +606,12 @@ struct ipr_mode_page28 {
|
|||
struct ipr_dev_bus_entry bus[0];
|
||||
}__attribute__((packed));
|
||||
|
||||
struct ipr_mode_page24 {
|
||||
struct ipr_mode_page_hdr hdr;
|
||||
u8 flags;
|
||||
#define IPR_ENABLE_DUAL_IOA_AF 0x80
|
||||
}__attribute__((packed));
|
||||
|
||||
struct ipr_ioa_vpd {
|
||||
struct ipr_std_inq_data std_inq_data;
|
||||
u8 ascii_part_num[12];
|
||||
|
@ -624,6 +634,19 @@ struct ipr_inquiry_page3 {
|
|||
u8 patch_number[4];
|
||||
}__attribute__((packed));
|
||||
|
||||
struct ipr_inquiry_cap {
|
||||
u8 peri_qual_dev_type;
|
||||
u8 page_code;
|
||||
u8 reserved1;
|
||||
u8 page_length;
|
||||
u8 ascii_len;
|
||||
u8 reserved2;
|
||||
u8 sis_version[2];
|
||||
u8 cap;
|
||||
#define IPR_CAP_DUAL_IOA_RAID 0x80
|
||||
u8 reserved3[15];
|
||||
}__attribute__((packed));
|
||||
|
||||
#define IPR_INQUIRY_PAGE0_ENTRIES 20
|
||||
struct ipr_inquiry_page0 {
|
||||
u8 peri_qual_dev_type;
|
||||
|
@ -962,6 +985,7 @@ struct ipr_misc_cbs {
|
|||
struct ipr_ioa_vpd ioa_vpd;
|
||||
struct ipr_inquiry_page0 page0_data;
|
||||
struct ipr_inquiry_page3 page3_data;
|
||||
struct ipr_inquiry_cap cap;
|
||||
struct ipr_mode_pages mode_pages;
|
||||
struct ipr_supported_device supp_dev;
|
||||
};
|
||||
|
@ -1068,6 +1092,10 @@ struct ipr_ioa_cfg {
|
|||
u8 allow_cmds:1;
|
||||
u8 allow_ml_add_del:1;
|
||||
u8 needs_hard_reset:1;
|
||||
u8 dual_raid:1;
|
||||
u8 needs_warm_reset:1;
|
||||
|
||||
u8 revid;
|
||||
|
||||
enum ipr_cache_state cache_state;
|
||||
u16 type; /* CCIN of the card */
|
||||
|
@ -1161,6 +1189,7 @@ struct ipr_ioa_cfg {
|
|||
struct pci_pool *ipr_cmd_pool;
|
||||
|
||||
struct ipr_cmnd *reset_cmd;
|
||||
int (*reset) (struct ipr_cmnd *);
|
||||
|
||||
struct ata_host ata_host;
|
||||
char ipr_cmd_label[8];
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/kthread.h>
|
||||
|
||||
#include "sas_internal.h"
|
||||
|
||||
#include <scsi/scsi_host.h>
|
||||
|
@ -184,7 +186,7 @@ static int sas_queue_up(struct sas_task *task)
|
|||
list_add_tail(&task->list, &core->task_queue);
|
||||
core->task_queue_size += 1;
|
||||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
up(&core->queue_thread_sema);
|
||||
wake_up_process(core->queue_thread);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -819,7 +821,7 @@ static void sas_queue(struct sas_ha_struct *sas_ha)
|
|||
struct sas_internal *i = to_sas_internal(core->shost->transportt);
|
||||
|
||||
spin_lock_irqsave(&core->task_queue_lock, flags);
|
||||
while (!core->queue_thread_kill &&
|
||||
while (!kthread_should_stop() &&
|
||||
!list_empty(&core->task_queue)) {
|
||||
|
||||
can_queue = sas_ha->lldd_queue_size - core->task_queue_size;
|
||||
|
@ -858,8 +860,6 @@ static void sas_queue(struct sas_ha_struct *sas_ha)
|
|||
spin_unlock_irqrestore(&core->task_queue_lock, flags);
|
||||
}
|
||||
|
||||
static DECLARE_COMPLETION(queue_th_comp);
|
||||
|
||||
/**
|
||||
* sas_queue_thread -- The Task Collector thread
|
||||
* @_sas_ha: pointer to struct sas_ha
|
||||
|
@ -867,40 +867,33 @@ static DECLARE_COMPLETION(queue_th_comp);
|
|||
static int sas_queue_thread(void *_sas_ha)
|
||||
{
|
||||
struct sas_ha_struct *sas_ha = _sas_ha;
|
||||
struct scsi_core *core = &sas_ha->core;
|
||||
|
||||
daemonize("sas_queue_%d", core->shost->host_no);
|
||||
current->flags |= PF_NOFREEZE;
|
||||
|
||||
complete(&queue_th_comp);
|
||||
|
||||
while (1) {
|
||||
down_interruptible(&core->queue_thread_sema);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
sas_queue(sas_ha);
|
||||
if (core->queue_thread_kill)
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
}
|
||||
|
||||
complete(&queue_th_comp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sas_init_queue(struct sas_ha_struct *sas_ha)
|
||||
{
|
||||
int res;
|
||||
struct scsi_core *core = &sas_ha->core;
|
||||
|
||||
spin_lock_init(&core->task_queue_lock);
|
||||
core->task_queue_size = 0;
|
||||
INIT_LIST_HEAD(&core->task_queue);
|
||||
init_MUTEX_LOCKED(&core->queue_thread_sema);
|
||||
|
||||
res = kernel_thread(sas_queue_thread, sas_ha, 0);
|
||||
if (res >= 0)
|
||||
wait_for_completion(&queue_th_comp);
|
||||
|
||||
return res < 0 ? res : 0;
|
||||
core->queue_thread = kthread_run(sas_queue_thread, sas_ha,
|
||||
"sas_queue_%d", core->shost->host_no);
|
||||
if (IS_ERR(core->queue_thread))
|
||||
return PTR_ERR(core->queue_thread);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
|
||||
|
@ -909,10 +902,7 @@ void sas_shutdown_queue(struct sas_ha_struct *sas_ha)
|
|||
struct scsi_core *core = &sas_ha->core;
|
||||
struct sas_task *task, *n;
|
||||
|
||||
init_completion(&queue_th_comp);
|
||||
core->queue_thread_kill = 1;
|
||||
up(&core->queue_thread_sema);
|
||||
wait_for_completion(&queue_th_comp);
|
||||
kthread_stop(core->queue_thread);
|
||||
|
||||
if (!list_empty(&core->task_queue))
|
||||
SAS_DPRINTK("HA: %llx: scsi core task queue is NOT empty!?\n",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||
|
@ -27,10 +27,6 @@ struct lpfc_sli2_slim;
|
|||
requests */
|
||||
#define LPFC_MAX_NS_RETRY 3 /* Number of retry attempts to contact
|
||||
the NameServer before giving up. */
|
||||
#define LPFC_DFT_HBA_Q_DEPTH 2048 /* max cmds per hba */
|
||||
#define LPFC_LC_HBA_Q_DEPTH 1024 /* max cmds per low cost hba */
|
||||
#define LPFC_LP101_HBA_Q_DEPTH 128 /* max cmds per low cost hba */
|
||||
|
||||
#define LPFC_CMD_PER_LUN 3 /* max outstanding cmds per lun */
|
||||
#define LPFC_SG_SEG_CNT 64 /* sg element count per scsi cmnd */
|
||||
#define LPFC_IOCB_LIST_CNT 2250 /* list of IOCBs for fast-path usage. */
|
||||
|
@ -244,28 +240,23 @@ struct lpfc_hba {
|
|||
#define FC_FABRIC 0x100 /* We are fabric attached */
|
||||
#define FC_ESTABLISH_LINK 0x200 /* Reestablish Link */
|
||||
#define FC_RSCN_DISCOVERY 0x400 /* Authenticate all devices after RSCN*/
|
||||
#define FC_BLOCK_MGMT_IO 0x800 /* Don't allow mgmt mbx or iocb cmds */
|
||||
#define FC_LOADING 0x1000 /* HBA in process of loading drvr */
|
||||
#define FC_UNLOADING 0x2000 /* HBA in process of unloading drvr */
|
||||
#define FC_SCSI_SCAN_TMO 0x4000 /* scsi scan timer running */
|
||||
#define FC_ABORT_DISCOVERY 0x8000 /* we want to abort discovery */
|
||||
#define FC_NDISC_ACTIVE 0x10000 /* NPort discovery active */
|
||||
#define FC_BYPASSED_MODE 0x20000 /* NPort is in bypassed mode */
|
||||
#define FC_LOOPBACK_MODE 0x40000 /* NPort is in Loopback mode */
|
||||
/* This flag is set while issuing */
|
||||
/* INIT_LINK mailbox command */
|
||||
#define FC_IGNORE_ERATT 0x80000 /* intr handler should ignore ERATT */
|
||||
|
||||
uint32_t fc_topology; /* link topology, from LINK INIT */
|
||||
|
||||
struct lpfc_stats fc_stat;
|
||||
|
||||
/* These are the head/tail pointers for the bind, plogi, adisc, unmap,
|
||||
* and map lists. Their counters are immediately following.
|
||||
*/
|
||||
struct list_head fc_plogi_list;
|
||||
struct list_head fc_adisc_list;
|
||||
struct list_head fc_reglogin_list;
|
||||
struct list_head fc_prli_list;
|
||||
struct list_head fc_nlpunmap_list;
|
||||
struct list_head fc_nlpmap_list;
|
||||
struct list_head fc_npr_list;
|
||||
struct list_head fc_unused_list;
|
||||
struct list_head fc_nodes;
|
||||
|
||||
/* Keep counters for the number of entries in each list. */
|
||||
uint16_t fc_plogi_cnt;
|
||||
|
@ -387,13 +378,17 @@ struct lpfc_hba {
|
|||
|
||||
mempool_t *mbox_mem_pool;
|
||||
mempool_t *nlp_mem_pool;
|
||||
struct list_head freebufList;
|
||||
struct list_head ctrspbuflist;
|
||||
struct list_head rnidrspbuflist;
|
||||
|
||||
struct fc_host_statistics link_stats;
|
||||
};
|
||||
|
||||
static inline void
|
||||
lpfc_set_loopback_flag(struct lpfc_hba *phba) {
|
||||
if (phba->cfg_topology == FLAGS_LOCAL_LB)
|
||||
phba->fc_flag |= FC_LOOPBACK_MODE;
|
||||
else
|
||||
phba->fc_flag &= ~FC_LOOPBACK_MODE;
|
||||
}
|
||||
|
||||
struct rnidrsp {
|
||||
void *buf;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||
|
@ -20,6 +20,7 @@
|
|||
*******************************************************************/
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
|
@ -213,6 +214,7 @@ lpfc_issue_lip(struct Scsi_Host *host)
|
|||
int mbxstatus = MBXERR_ERROR;
|
||||
|
||||
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
|
||||
(phba->fc_flag & FC_BLOCK_MGMT_IO) ||
|
||||
(phba->hba_state != LPFC_HBA_READY))
|
||||
return -EPERM;
|
||||
|
||||
|
@ -235,6 +237,7 @@ lpfc_issue_lip(struct Scsi_Host *host)
|
|||
phba->fc_ratov * 2);
|
||||
}
|
||||
|
||||
lpfc_set_loopback_flag(phba);
|
||||
if (mbxstatus == MBX_TIMEOUT)
|
||||
pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||
else
|
||||
|
@ -246,19 +249,62 @@ lpfc_issue_lip(struct Scsi_Host *host)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_do_offline(struct lpfc_hba *phba, uint32_t type)
|
||||
{
|
||||
struct completion online_compl;
|
||||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_sli *psli;
|
||||
int status = 0;
|
||||
int cnt = 0;
|
||||
int i;
|
||||
|
||||
init_completion(&online_compl);
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_OFFLINE_PREP);
|
||||
wait_for_completion(&online_compl);
|
||||
|
||||
if (status != 0)
|
||||
return -EIO;
|
||||
|
||||
psli = &phba->sli;
|
||||
|
||||
for (i = 0; i < psli->num_rings; i++) {
|
||||
pring = &psli->ring[i];
|
||||
/* The linkdown event takes 30 seconds to timeout. */
|
||||
while (pring->txcmplq_cnt) {
|
||||
msleep(10);
|
||||
if (cnt++ > 3000) {
|
||||
lpfc_printf_log(phba,
|
||||
KERN_WARNING, LOG_INIT,
|
||||
"%d:0466 Outstanding IO when "
|
||||
"bringing Adapter offline\n",
|
||||
phba->brd_no);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init_completion(&online_compl);
|
||||
lpfc_workq_post_event(phba, &status, &online_compl, type);
|
||||
wait_for_completion(&online_compl);
|
||||
|
||||
if (status != 0)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_selective_reset(struct lpfc_hba *phba)
|
||||
{
|
||||
struct completion online_compl;
|
||||
int status = 0;
|
||||
|
||||
init_completion(&online_compl);
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_OFFLINE);
|
||||
wait_for_completion(&online_compl);
|
||||
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
|
||||
|
||||
if (status != 0)
|
||||
return -EIO;
|
||||
return status;
|
||||
|
||||
init_completion(&online_compl);
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
|
@ -324,23 +370,19 @@ lpfc_board_mode_store(struct class_device *cdev, const char *buf, size_t count)
|
|||
|
||||
init_completion(&online_compl);
|
||||
|
||||
if(strncmp(buf, "online", sizeof("online") - 1) == 0)
|
||||
if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_ONLINE);
|
||||
else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_OFFLINE);
|
||||
wait_for_completion(&online_compl);
|
||||
} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
|
||||
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
|
||||
else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_WARM_START);
|
||||
else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
|
||||
lpfc_workq_post_event(phba, &status, &online_compl,
|
||||
LPFC_EVT_KILL);
|
||||
status = lpfc_do_offline(phba, LPFC_EVT_WARM_START);
|
||||
else if (strncmp(buf, "error", sizeof("error") - 1) == 0)
|
||||
status = lpfc_do_offline(phba, LPFC_EVT_KILL);
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
wait_for_completion(&online_compl);
|
||||
|
||||
if (!status)
|
||||
return strlen(buf);
|
||||
else
|
||||
|
@ -645,9 +687,7 @@ lpfc_soft_wwpn_store(struct class_device *cdev, const char *buf, size_t count)
|
|||
dev_printk(KERN_NOTICE, &phba->pcidev->dev,
|
||||
"lpfc%d: Reinitializing to use soft_wwpn\n", phba->brd_no);
|
||||
|
||||
init_completion(&online_compl);
|
||||
lpfc_workq_post_event(phba, &stat1, &online_compl, LPFC_EVT_OFFLINE);
|
||||
wait_for_completion(&online_compl);
|
||||
stat1 = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
|
||||
if (stat1)
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"%d:0463 lpfc_soft_wwpn attribute set failed to reinit "
|
||||
|
@ -789,6 +829,18 @@ lpfc_nodev_tmo_init(struct lpfc_hba *phba, int val)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_update_rport_devloss_tmo(struct lpfc_hba *phba)
|
||||
{
|
||||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp)
|
||||
if (ndlp->rport)
|
||||
ndlp->rport->dev_loss_tmo = phba->cfg_devloss_tmo;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val)
|
||||
{
|
||||
|
@ -804,6 +856,7 @@ lpfc_nodev_tmo_set(struct lpfc_hba *phba, int val)
|
|||
if (val >= LPFC_MIN_DEVLOSS_TMO && val <= LPFC_MAX_DEVLOSS_TMO) {
|
||||
phba->cfg_nodev_tmo = val;
|
||||
phba->cfg_devloss_tmo = val;
|
||||
lpfc_update_rport_devloss_tmo(phba);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -839,6 +892,7 @@ lpfc_devloss_tmo_set(struct lpfc_hba *phba, int val)
|
|||
phba->cfg_nodev_tmo = val;
|
||||
phba->cfg_devloss_tmo = val;
|
||||
phba->dev_loss_tmo_changed = 1;
|
||||
lpfc_update_rport_devloss_tmo(phba);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -931,9 +985,10 @@ LPFC_ATTR_RW(topology, 0, 0, 6, "Select Fibre Channel topology");
|
|||
# 1 = 1 Gigabaud
|
||||
# 2 = 2 Gigabaud
|
||||
# 4 = 4 Gigabaud
|
||||
# Value range is [0,4]. Default value is 0.
|
||||
# 8 = 8 Gigabaud
|
||||
# Value range is [0,8]. Default value is 0.
|
||||
*/
|
||||
LPFC_ATTR_R(link_speed, 0, 0, 4, "Select link speed");
|
||||
LPFC_ATTR_R(link_speed, 0, 0, 8, "Select link speed");
|
||||
|
||||
/*
|
||||
# lpfc_fcp_class: Determines FC class to use for the FCP protocol.
|
||||
|
@ -958,7 +1013,7 @@ LPFC_ATTR_R(ack0, 0, 0, 1, "Enable ACK0 support");
|
|||
/*
|
||||
# lpfc_cr_delay & lpfc_cr_count: Default values for I/O colaesing
|
||||
# cr_delay (msec) or cr_count outstanding commands. cr_delay can take
|
||||
# value [0,63]. cr_count can take value [0,255]. Default value of cr_delay
|
||||
# value [0,63]. cr_count can take value [1,255]. Default value of cr_delay
|
||||
# is 0. Default value of cr_count is 1. The cr_count feature is disabled if
|
||||
# cr_delay is set to 0.
|
||||
*/
|
||||
|
@ -1227,11 +1282,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
|||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
int rc;
|
||||
|
||||
if (off > sizeof(MAILBOX_t))
|
||||
if (off > MAILBOX_CMD_SIZE)
|
||||
return -ERANGE;
|
||||
|
||||
if ((count + off) > sizeof(MAILBOX_t))
|
||||
count = sizeof(MAILBOX_t) - off;
|
||||
if ((count + off) > MAILBOX_CMD_SIZE)
|
||||
count = MAILBOX_CMD_SIZE - off;
|
||||
|
||||
if (off % 4 || count % 4 || (unsigned long)buf % 4)
|
||||
return -EINVAL;
|
||||
|
@ -1307,6 +1362,12 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
if (phba->fc_flag & FC_BLOCK_MGMT_IO) {
|
||||
sysfs_mbox_idle(phba);
|
||||
spin_unlock_irq(host->host_lock);
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if ((phba->fc_flag & FC_OFFLINE_MODE) ||
|
||||
(!(phba->sli.sli_flag & LPFC_SLI2_ACTIVE))){
|
||||
|
||||
|
@ -1326,6 +1387,11 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
|||
}
|
||||
|
||||
if (rc != MBX_SUCCESS) {
|
||||
if (rc == MBX_TIMEOUT) {
|
||||
phba->sysfs_mbox.mbox->mbox_cmpl =
|
||||
lpfc_sli_def_mbox_cmpl;
|
||||
phba->sysfs_mbox.mbox = NULL;
|
||||
}
|
||||
sysfs_mbox_idle(phba);
|
||||
spin_unlock_irq(host->host_lock);
|
||||
return (rc == MBX_TIMEOUT) ? -ETIME : -ENODEV;
|
||||
|
@ -1344,7 +1410,7 @@ sysfs_mbox_read(struct kobject *kobj, char *buf, loff_t off, size_t count)
|
|||
|
||||
phba->sysfs_mbox.offset = off + count;
|
||||
|
||||
if (phba->sysfs_mbox.offset == sizeof(MAILBOX_t))
|
||||
if (phba->sysfs_mbox.offset == MAILBOX_CMD_SIZE)
|
||||
sysfs_mbox_idle(phba);
|
||||
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
@ -1358,7 +1424,7 @@ static struct bin_attribute sysfs_mbox_attr = {
|
|||
.mode = S_IRUSR | S_IWUSR,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.size = sizeof(MAILBOX_t),
|
||||
.size = MAILBOX_CMD_SIZE,
|
||||
.read = sysfs_mbox_read,
|
||||
.write = sysfs_mbox_write,
|
||||
};
|
||||
|
@ -1494,6 +1560,9 @@ lpfc_get_host_speed(struct Scsi_Host *shost)
|
|||
case LA_4GHZ_LINK:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_4GBIT;
|
||||
break;
|
||||
case LA_8GHZ_LINK:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_8GBIT;
|
||||
break;
|
||||
default:
|
||||
fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
|
||||
break;
|
||||
|
@ -1546,6 +1615,9 @@ lpfc_get_stats(struct Scsi_Host *shost)
|
|||
unsigned long seconds;
|
||||
int rc = 0;
|
||||
|
||||
if (phba->fc_flag & FC_BLOCK_MGMT_IO)
|
||||
return NULL;
|
||||
|
||||
pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (!pmboxq)
|
||||
return NULL;
|
||||
|
@ -1631,6 +1703,8 @@ lpfc_get_stats(struct Scsi_Host *shost)
|
|||
else
|
||||
hs->seconds_since_last_reset = seconds - psli->stats_start;
|
||||
|
||||
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||
|
||||
return hs;
|
||||
}
|
||||
|
||||
|
@ -1644,6 +1718,9 @@ lpfc_reset_stats(struct Scsi_Host *shost)
|
|||
MAILBOX_t *pmb;
|
||||
int rc = 0;
|
||||
|
||||
if (phba->fc_flag & FC_BLOCK_MGMT_IO)
|
||||
return;
|
||||
|
||||
pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
|
||||
if (!pmboxq)
|
||||
return;
|
||||
|
@ -1699,6 +1776,8 @@ lpfc_reset_stats(struct Scsi_Host *shost)
|
|||
|
||||
psli->stats_start = get_seconds();
|
||||
|
||||
mempool_free(pmboxq, phba->mbox_mem_pool);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1706,67 +1785,51 @@ lpfc_reset_stats(struct Scsi_Host *shost)
|
|||
* The LPFC driver treats linkdown handling as target loss events so there
|
||||
* are no sysfs handlers for link_down_tmo.
|
||||
*/
|
||||
static void
|
||||
lpfc_get_starget_port_id(struct scsi_target *starget)
|
||||
|
||||
static struct lpfc_nodelist *
|
||||
lpfc_get_node_by_target(struct scsi_target *starget)
|
||||
{
|
||||
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
|
||||
uint32_t did = -1;
|
||||
struct lpfc_nodelist *ndlp = NULL;
|
||||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
/* Search the mapped list for this target ID */
|
||||
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
|
||||
if (starget->id == ndlp->nlp_sid) {
|
||||
did = ndlp->nlp_DID;
|
||||
break;
|
||||
/* Search for this, mapped, target ID */
|
||||
list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
|
||||
if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
|
||||
starget->id == ndlp->nlp_sid) {
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
return ndlp;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fc_starget_port_id(starget) = did;
|
||||
static void
|
||||
lpfc_get_starget_port_id(struct scsi_target *starget)
|
||||
{
|
||||
struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget);
|
||||
|
||||
fc_starget_port_id(starget) = ndlp ? ndlp->nlp_DID : -1;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_get_starget_node_name(struct scsi_target *starget)
|
||||
{
|
||||
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
|
||||
u64 node_name = 0;
|
||||
struct lpfc_nodelist *ndlp = NULL;
|
||||
struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget);
|
||||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
/* Search the mapped list for this target ID */
|
||||
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
|
||||
if (starget->id == ndlp->nlp_sid) {
|
||||
node_name = wwn_to_u64(ndlp->nlp_nodename.u.wwn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
||||
fc_starget_node_name(starget) = node_name;
|
||||
fc_starget_node_name(starget) =
|
||||
ndlp ? wwn_to_u64(ndlp->nlp_nodename.u.wwn) : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_get_starget_port_name(struct scsi_target *starget)
|
||||
{
|
||||
struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata;
|
||||
u64 port_name = 0;
|
||||
struct lpfc_nodelist *ndlp = NULL;
|
||||
struct lpfc_nodelist *ndlp = lpfc_get_node_by_target(starget);
|
||||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
/* Search the mapped list for this target ID */
|
||||
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
|
||||
if (starget->id == ndlp->nlp_sid) {
|
||||
port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
||||
fc_starget_port_name(starget) = port_name;
|
||||
fc_starget_port_name(starget) =
|
||||
ndlp ? wwn_to_u64(ndlp->nlp_portname.u.wwn) : 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1895,25 +1958,8 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
|
|||
sizeof(struct fcp_rsp) +
|
||||
(phba->cfg_sg_seg_cnt * sizeof(struct ulp_bde64));
|
||||
|
||||
switch (phba->pcidev->device) {
|
||||
case PCI_DEVICE_ID_LP101:
|
||||
case PCI_DEVICE_ID_BSMB:
|
||||
case PCI_DEVICE_ID_ZSMB:
|
||||
phba->cfg_hba_queue_depth = LPFC_LP101_HBA_Q_DEPTH;
|
||||
break;
|
||||
case PCI_DEVICE_ID_RFLY:
|
||||
case PCI_DEVICE_ID_PFLY:
|
||||
case PCI_DEVICE_ID_BMID:
|
||||
case PCI_DEVICE_ID_ZMID:
|
||||
case PCI_DEVICE_ID_TFLY:
|
||||
phba->cfg_hba_queue_depth = LPFC_LC_HBA_Q_DEPTH;
|
||||
break;
|
||||
default:
|
||||
phba->cfg_hba_queue_depth = LPFC_DFT_HBA_Q_DEPTH;
|
||||
}
|
||||
|
||||
if (phba->cfg_hba_queue_depth > lpfc_hba_queue_depth)
|
||||
lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
|
||||
lpfc_hba_queue_depth_init(phba, lpfc_hba_queue_depth);
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -18,6 +18,8 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
typedef int (*node_filter)(struct lpfc_nodelist *ndlp, void *param);
|
||||
|
||||
struct fc_rport;
|
||||
void lpfc_dump_mem(struct lpfc_hba *, LPFC_MBOXQ_t *, uint16_t);
|
||||
void lpfc_read_nv(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
|
@ -43,20 +45,24 @@ void lpfc_mbx_cmpl_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
|||
void lpfc_mbx_cmpl_fabric_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_ns_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
void lpfc_mbx_cmpl_fdmi_reg_login(struct lpfc_hba *, LPFC_MBOXQ_t *);
|
||||
int lpfc_nlp_list(struct lpfc_hba *, struct lpfc_nodelist *, int);
|
||||
void lpfc_dequeue_node(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
void lpfc_nlp_set_state(struct lpfc_hba *, struct lpfc_nodelist *, int);
|
||||
void lpfc_drop_node(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
void lpfc_set_disctmo(struct lpfc_hba *);
|
||||
int lpfc_can_disctmo(struct lpfc_hba *);
|
||||
int lpfc_unreg_rpi(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
int lpfc_check_sli_ndlp(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *, struct lpfc_nodelist *);
|
||||
int lpfc_nlp_remove(struct lpfc_hba *, struct lpfc_nodelist *);
|
||||
void lpfc_nlp_init(struct lpfc_hba *, struct lpfc_nodelist *, uint32_t);
|
||||
struct lpfc_nodelist *lpfc_nlp_get(struct lpfc_nodelist *);
|
||||
int lpfc_nlp_put(struct lpfc_nodelist *);
|
||||
struct lpfc_nodelist *lpfc_setup_disc_node(struct lpfc_hba *, uint32_t);
|
||||
void lpfc_disc_list_loopmap(struct lpfc_hba *);
|
||||
void lpfc_disc_start(struct lpfc_hba *);
|
||||
void lpfc_disc_flush_list(struct lpfc_hba *);
|
||||
void lpfc_disc_timeout(unsigned long);
|
||||
|
||||
struct lpfc_nodelist *__lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
|
||||
struct lpfc_nodelist *lpfc_findnode_rpi(struct lpfc_hba * phba, uint16_t rpi);
|
||||
|
||||
int lpfc_workq_post_event(struct lpfc_hba *, void *, void *, uint32_t);
|
||||
|
@ -66,8 +72,7 @@ int lpfc_disc_state_machine(struct lpfc_hba *, struct lpfc_nodelist *, void *,
|
|||
|
||||
int lpfc_check_sparm(struct lpfc_hba *, struct lpfc_nodelist *,
|
||||
struct serv_parm *, uint32_t);
|
||||
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp,
|
||||
int);
|
||||
int lpfc_els_abort(struct lpfc_hba *, struct lpfc_nodelist * ndlp);
|
||||
int lpfc_els_abort_flogi(struct lpfc_hba *);
|
||||
int lpfc_initial_flogi(struct lpfc_hba *);
|
||||
int lpfc_issue_els_plogi(struct lpfc_hba *, uint32_t, uint8_t);
|
||||
|
@ -113,7 +118,10 @@ void lpfc_hba_init(struct lpfc_hba *, uint32_t *);
|
|||
int lpfc_post_buffer(struct lpfc_hba *, struct lpfc_sli_ring *, int, int);
|
||||
void lpfc_decode_firmware_rev(struct lpfc_hba *, char *, int);
|
||||
int lpfc_online(struct lpfc_hba *);
|
||||
int lpfc_offline(struct lpfc_hba *);
|
||||
void lpfc_block_mgmt_io(struct lpfc_hba *);
|
||||
void lpfc_unblock_mgmt_io(struct lpfc_hba *);
|
||||
void lpfc_offline_prep(struct lpfc_hba *);
|
||||
void lpfc_offline(struct lpfc_hba *);
|
||||
|
||||
int lpfc_sli_setup(struct lpfc_hba *);
|
||||
int lpfc_sli_queue_setup(struct lpfc_hba *);
|
||||
|
@ -162,8 +170,8 @@ int lpfc_sli_ringpostbuf_put(struct lpfc_hba *, struct lpfc_sli_ring *,
|
|||
struct lpfc_dmabuf *lpfc_sli_ringpostbuf_get(struct lpfc_hba *,
|
||||
struct lpfc_sli_ring *,
|
||||
dma_addr_t);
|
||||
int lpfc_sli_issue_abort_iotag32(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *);
|
||||
int lpfc_sli_issue_abort_iotag(struct lpfc_hba *, struct lpfc_sli_ring *,
|
||||
struct lpfc_iocbq *);
|
||||
int lpfc_sli_sum_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
|
||||
uint64_t, lpfc_ctx_cmd);
|
||||
int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
|
||||
|
@ -172,9 +180,8 @@ int lpfc_sli_abort_iocb(struct lpfc_hba *, struct lpfc_sli_ring *, uint16_t,
|
|||
void lpfc_mbox_timeout(unsigned long);
|
||||
void lpfc_mbox_timeout_handler(struct lpfc_hba *);
|
||||
|
||||
struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t, uint32_t);
|
||||
struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, uint32_t,
|
||||
struct lpfc_name *);
|
||||
struct lpfc_nodelist *lpfc_findnode_did(struct lpfc_hba *, uint32_t);
|
||||
struct lpfc_nodelist *lpfc_findnode_wwpn(struct lpfc_hba *, struct lpfc_name *);
|
||||
|
||||
int lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
|
||||
uint32_t timeout);
|
||||
|
@ -193,6 +200,9 @@ void lpfc_mbuf_free(struct lpfc_hba *, void *, dma_addr_t);
|
|||
|
||||
/* Function prototypes. */
|
||||
const char* lpfc_info(struct Scsi_Host *);
|
||||
void lpfc_scan_start(struct Scsi_Host *);
|
||||
int lpfc_scan_finished(struct Scsi_Host *, unsigned long);
|
||||
|
||||
void lpfc_get_cfgparam(struct lpfc_hba *);
|
||||
int lpfc_alloc_sysfs_attr(struct lpfc_hba *);
|
||||
void lpfc_free_sysfs_attr(struct lpfc_hba *);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -334,21 +334,22 @@ lpfc_ns_rsp(struct lpfc_hba * phba, struct lpfc_dmabuf * mp, uint32_t Size)
|
|||
|
||||
lpfc_set_disctmo(phba);
|
||||
|
||||
Cnt = Size > FCELSSIZE ? FCELSSIZE : Size;
|
||||
|
||||
list_add_tail(&head, &mp->list);
|
||||
list_for_each_entry_safe(mp, next_mp, &head, list) {
|
||||
mlast = mp;
|
||||
|
||||
Cnt = Size > FCELSSIZE ? FCELSSIZE : Size;
|
||||
|
||||
Size -= Cnt;
|
||||
|
||||
if (!ctptr)
|
||||
if (!ctptr) {
|
||||
ctptr = (uint32_t *) mlast->virt;
|
||||
else
|
||||
} else
|
||||
Cnt -= 16; /* subtract length of CT header */
|
||||
|
||||
/* Loop through entire NameServer list of DIDs */
|
||||
while (Cnt) {
|
||||
while (Cnt >= sizeof (uint32_t)) {
|
||||
|
||||
/* Get next DID from NameServer List */
|
||||
CTentry = *ctptr++;
|
||||
|
@ -442,10 +443,8 @@ lpfc_cmpl_ct_cmd_gid_ft(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
|||
if (phba->fc_ns_retry < LPFC_MAX_NS_RETRY) {
|
||||
phba->fc_ns_retry++;
|
||||
/* CT command is being retried */
|
||||
ndlp =
|
||||
lpfc_findnode_did(phba, NLP_SEARCH_UNMAPPED,
|
||||
NameServer_DID);
|
||||
if (ndlp) {
|
||||
ndlp = lpfc_findnode_did(phba, NameServer_DID);
|
||||
if (ndlp && ndlp->nlp_state == NLP_STE_UNMAPPED_NODE) {
|
||||
if (lpfc_ns_cmd(phba, ndlp, SLI_CTNS_GID_FT) ==
|
||||
0) {
|
||||
goto out;
|
||||
|
@ -729,7 +728,7 @@ lpfc_cmpl_ct_cmd_fdmi(struct lpfc_hba * phba,
|
|||
uint16_t fdmi_cmd = CTcmd->CommandResponse.bits.CmdRsp;
|
||||
uint16_t fdmi_rsp = CTrsp->CommandResponse.bits.CmdRsp;
|
||||
|
||||
ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID);
|
||||
ndlp = lpfc_findnode_did(phba, FDMI_DID);
|
||||
if (fdmi_rsp == be16_to_cpu(SLI_CT_RESPONSE_FS_RJT)) {
|
||||
/* FDMI rsp failed */
|
||||
lpfc_printf_log(phba,
|
||||
|
@ -1039,6 +1038,9 @@ lpfc_fdmi_cmd(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp, int cmdcode)
|
|||
case LA_4GHZ_LINK:
|
||||
ae->un.PortSpeed = HBA_PORTSPEED_4GBIT;
|
||||
break;
|
||||
case LA_8GHZ_LINK:
|
||||
ae->un.PortSpeed = HBA_PORTSPEED_8GBIT;
|
||||
break;
|
||||
default:
|
||||
ae->un.PortSpeed =
|
||||
HBA_PORTSPEED_UNKNOWN;
|
||||
|
@ -1161,7 +1163,7 @@ lpfc_fdmi_tmo_handler(struct lpfc_hba *phba)
|
|||
{
|
||||
struct lpfc_nodelist *ndlp;
|
||||
|
||||
ndlp = lpfc_findnode_did(phba, NLP_SEARCH_ALL, FDMI_DID);
|
||||
ndlp = lpfc_findnode_did(phba, FDMI_DID);
|
||||
if (ndlp) {
|
||||
if (init_utsname()->nodename[0] != '\0') {
|
||||
lpfc_fdmi_cmd(phba, ndlp, SLI_MGMT_DHBA);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -31,6 +31,7 @@
|
|||
/* worker thread events */
|
||||
enum lpfc_work_type {
|
||||
LPFC_EVT_ONLINE,
|
||||
LPFC_EVT_OFFLINE_PREP,
|
||||
LPFC_EVT_OFFLINE,
|
||||
LPFC_EVT_WARM_START,
|
||||
LPFC_EVT_KILL,
|
||||
|
@ -68,7 +69,6 @@ struct lpfc_nodelist {
|
|||
uint16_t nlp_maxframe; /* Max RCV frame size */
|
||||
uint8_t nlp_class_sup; /* Supported Classes */
|
||||
uint8_t nlp_retry; /* used for ELS retries */
|
||||
uint8_t nlp_disc_refcnt; /* used for DSM */
|
||||
uint8_t nlp_fcp_info; /* class info, bits 0-3 */
|
||||
#define NLP_FCP_2_DEVICE 0x10 /* FCP-2 device */
|
||||
|
||||
|
@ -79,20 +79,10 @@ struct lpfc_nodelist {
|
|||
struct lpfc_work_evt els_retry_evt;
|
||||
unsigned long last_ramp_up_time; /* jiffy of last ramp up */
|
||||
unsigned long last_q_full_time; /* jiffy of last queue full */
|
||||
struct kref kref;
|
||||
};
|
||||
|
||||
/* Defines for nlp_flag (uint32) */
|
||||
#define NLP_NO_LIST 0x0 /* Indicates immediately free node */
|
||||
#define NLP_UNUSED_LIST 0x1 /* Flg to indicate node will be freed */
|
||||
#define NLP_PLOGI_LIST 0x2 /* Flg to indicate sent PLOGI */
|
||||
#define NLP_ADISC_LIST 0x3 /* Flg to indicate sent ADISC */
|
||||
#define NLP_REGLOGIN_LIST 0x4 /* Flg to indicate sent REG_LOGIN */
|
||||
#define NLP_PRLI_LIST 0x5 /* Flg to indicate sent PRLI */
|
||||
#define NLP_UNMAPPED_LIST 0x6 /* Node is now unmapped */
|
||||
#define NLP_MAPPED_LIST 0x7 /* Node is now mapped */
|
||||
#define NLP_NPR_LIST 0x8 /* Node is in NPort Recovery state */
|
||||
#define NLP_JUST_DQ 0x9 /* just deque ndlp in lpfc_nlp_list */
|
||||
#define NLP_LIST_MASK 0xf /* mask to see what list node is on */
|
||||
#define NLP_PLOGI_SND 0x20 /* sent PLOGI request for this entry */
|
||||
#define NLP_PRLI_SND 0x40 /* sent PRLI request for this entry */
|
||||
#define NLP_ADISC_SND 0x80 /* sent ADISC request for this entry */
|
||||
|
@ -108,20 +98,8 @@ struct lpfc_nodelist {
|
|||
ACC */
|
||||
#define NLP_NPR_ADISC 0x2000000 /* Issue ADISC when dq'ed from
|
||||
NPR list */
|
||||
#define NLP_DELAY_REMOVE 0x4000000 /* Defer removal till end of DSM */
|
||||
#define NLP_NODEV_REMOVE 0x8000000 /* Defer removal till discovery ends */
|
||||
|
||||
/* Defines for list searchs */
|
||||
#define NLP_SEARCH_MAPPED 0x1 /* search mapped */
|
||||
#define NLP_SEARCH_UNMAPPED 0x2 /* search unmapped */
|
||||
#define NLP_SEARCH_PLOGI 0x4 /* search plogi */
|
||||
#define NLP_SEARCH_ADISC 0x8 /* search adisc */
|
||||
#define NLP_SEARCH_REGLOGIN 0x10 /* search reglogin */
|
||||
#define NLP_SEARCH_PRLI 0x20 /* search prli */
|
||||
#define NLP_SEARCH_NPR 0x40 /* search npr */
|
||||
#define NLP_SEARCH_UNUSED 0x80 /* search mapped */
|
||||
#define NLP_SEARCH_ALL 0xff /* search all lists */
|
||||
|
||||
/* There are 4 different double linked lists nodelist entries can reside on.
|
||||
* The Port Login (PLOGI) list and Address Discovery (ADISC) list are used
|
||||
* when Link Up discovery or Registered State Change Notification (RSCN)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -1078,6 +1078,8 @@ typedef struct {
|
|||
/* Start FireFly Register definitions */
|
||||
#define PCI_VENDOR_ID_EMULEX 0x10df
|
||||
#define PCI_DEVICE_ID_FIREFLY 0x1ae5
|
||||
#define PCI_DEVICE_ID_SAT_SMB 0xf011
|
||||
#define PCI_DEVICE_ID_SAT_MID 0xf015
|
||||
#define PCI_DEVICE_ID_RFLY 0xf095
|
||||
#define PCI_DEVICE_ID_PFLY 0xf098
|
||||
#define PCI_DEVICE_ID_LP101 0xf0a1
|
||||
|
@ -1089,6 +1091,9 @@ typedef struct {
|
|||
#define PCI_DEVICE_ID_NEPTUNE 0xf0f5
|
||||
#define PCI_DEVICE_ID_NEPTUNE_SCSP 0xf0f6
|
||||
#define PCI_DEVICE_ID_NEPTUNE_DCSP 0xf0f7
|
||||
#define PCI_DEVICE_ID_SAT 0xf100
|
||||
#define PCI_DEVICE_ID_SAT_SCSP 0xf111
|
||||
#define PCI_DEVICE_ID_SAT_DCSP 0xf112
|
||||
#define PCI_DEVICE_ID_SUPERFLY 0xf700
|
||||
#define PCI_DEVICE_ID_DRAGONFLY 0xf800
|
||||
#define PCI_DEVICE_ID_CENTAUR 0xf900
|
||||
|
@ -1098,6 +1103,7 @@ typedef struct {
|
|||
#define PCI_DEVICE_ID_LP10000S 0xfc00
|
||||
#define PCI_DEVICE_ID_LP11000S 0xfc10
|
||||
#define PCI_DEVICE_ID_LPE11000S 0xfc20
|
||||
#define PCI_DEVICE_ID_SAT_S 0xfc40
|
||||
#define PCI_DEVICE_ID_HELIOS 0xfd00
|
||||
#define PCI_DEVICE_ID_HELIOS_SCSP 0xfd11
|
||||
#define PCI_DEVICE_ID_HELIOS_DCSP 0xfd12
|
||||
|
@ -1118,6 +1124,7 @@ typedef struct {
|
|||
#define HELIOS_JEDEC_ID 0x0364
|
||||
#define ZEPHYR_JEDEC_ID 0x0577
|
||||
#define VIPER_JEDEC_ID 0x4838
|
||||
#define SATURN_JEDEC_ID 0x1004
|
||||
|
||||
#define JEDEC_ID_MASK 0x0FFFF000
|
||||
#define JEDEC_ID_SHIFT 12
|
||||
|
@ -1565,7 +1572,7 @@ typedef struct {
|
|||
#define LINK_SPEED_1G 1 /* 1 Gigabaud */
|
||||
#define LINK_SPEED_2G 2 /* 2 Gigabaud */
|
||||
#define LINK_SPEED_4G 4 /* 4 Gigabaud */
|
||||
#define LINK_SPEED_8G 8 /* 4 Gigabaud */
|
||||
#define LINK_SPEED_8G 8 /* 8 Gigabaud */
|
||||
#define LINK_SPEED_10G 16 /* 10 Gigabaud */
|
||||
|
||||
} INIT_LINK_VAR;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||
|
@ -386,12 +386,12 @@ lpfc_config_port_post(struct lpfc_hba * phba)
|
|||
* Setup the ring 0 (els) timeout handler
|
||||
*/
|
||||
timeout = phba->fc_ratov << 1;
|
||||
phba->els_tmofunc.expires = jiffies + HZ * timeout;
|
||||
add_timer(&phba->els_tmofunc);
|
||||
mod_timer(&phba->els_tmofunc, jiffies + HZ * timeout);
|
||||
|
||||
lpfc_init_link(phba, pmb, phba->cfg_topology, phba->cfg_link_speed);
|
||||
pmb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
|
||||
lpfc_set_loopback_flag(phba);
|
||||
if (rc != MBX_SUCCESS) {
|
||||
lpfc_printf_log(phba,
|
||||
KERN_ERR,
|
||||
|
@ -418,33 +418,6 @@ lpfc_config_port_post(struct lpfc_hba * phba)
|
|||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_discovery_wait(struct lpfc_hba *phba)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while ((phba->hba_state != LPFC_HBA_READY) ||
|
||||
(phba->num_disc_nodes) || (phba->fc_prli_sent) ||
|
||||
((phba->fc_map_cnt == 0) && (i<2)) ||
|
||||
(phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)) {
|
||||
/* Check every second for 30 retries. */
|
||||
i++;
|
||||
if (i > 30) {
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
if ((i >= 15) && (phba->hba_state <= LPFC_LINK_DOWN)) {
|
||||
/* The link is down. Set linkdown timeout */
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/* Delay for 1 second to give discovery time to complete. */
|
||||
msleep(1000);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/* lpfc_hba_down_prep */
|
||||
|
@ -550,12 +523,15 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
|
|||
* There was a firmware error. Take the hba offline and then
|
||||
* attempt to restart it.
|
||||
*/
|
||||
lpfc_offline_prep(phba);
|
||||
lpfc_offline(phba);
|
||||
lpfc_sli_brdrestart(phba);
|
||||
if (lpfc_online(phba) == 0) { /* Initialize the HBA */
|
||||
mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
return;
|
||||
}
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
} else {
|
||||
/* The if clause above forces this code path when the status
|
||||
* failure is a value other than FFER6. Do not call the offline
|
||||
|
@ -573,7 +549,9 @@ lpfc_handle_eratt(struct lpfc_hba * phba)
|
|||
SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_EMULEX);
|
||||
|
||||
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
|
||||
lpfc_offline_prep(phba);
|
||||
lpfc_offline(phba);
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
phba->hba_state = LPFC_HBA_ERROR;
|
||||
lpfc_hba_down_post(phba);
|
||||
}
|
||||
|
@ -633,7 +611,7 @@ lpfc_handle_latt(struct lpfc_hba * phba)
|
|||
lpfc_handle_latt_free_mp:
|
||||
kfree(mp);
|
||||
lpfc_handle_latt_free_pmb:
|
||||
kfree(pmb);
|
||||
mempool_free(pmb, phba->mbox_mem_pool);
|
||||
lpfc_handle_latt_err_exit:
|
||||
/* Enable Link attention interrupts */
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
|
@ -925,6 +903,24 @@ lpfc_get_hba_model_desc(struct lpfc_hba * phba, uint8_t * mdp, uint8_t * descp)
|
|||
m = (typeof(m)){"LPe11000-S", max_speed,
|
||||
"PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT:
|
||||
m = (typeof(m)){"LPe12000", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_MID:
|
||||
m = (typeof(m)){"LPe1250", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_SMB:
|
||||
m = (typeof(m)){"LPe121", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_DCSP:
|
||||
m = (typeof(m)){"LPe12002-SP", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_SCSP:
|
||||
m = (typeof(m)){"LPe12000-SP", max_speed, "PCIe"};
|
||||
break;
|
||||
case PCI_DEVICE_ID_SAT_S:
|
||||
m = (typeof(m)){"LPe12000-S", max_speed, "PCIe"};
|
||||
break;
|
||||
default:
|
||||
m = (typeof(m)){ NULL };
|
||||
break;
|
||||
|
@ -1174,69 +1170,17 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit)
|
|||
}
|
||||
|
||||
static void
|
||||
lpfc_cleanup(struct lpfc_hba * phba, uint32_t save_bind)
|
||||
lpfc_cleanup(struct lpfc_hba * phba)
|
||||
{
|
||||
struct lpfc_nodelist *ndlp, *next_ndlp;
|
||||
|
||||
/* clean up phba - lpfc specific */
|
||||
lpfc_can_disctmo(phba);
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpunmap_list,
|
||||
nlp_listp) {
|
||||
lpfc_nlp_remove(phba, ndlp);
|
||||
}
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
|
||||
lpfc_nlp_put(ndlp);
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nlpmap_list,
|
||||
nlp_listp) {
|
||||
lpfc_nlp_remove(phba, ndlp);
|
||||
}
|
||||
INIT_LIST_HEAD(&phba->fc_nodes);
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_unused_list,
|
||||
nlp_listp) {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_plogi_list,
|
||||
nlp_listp) {
|
||||
lpfc_nlp_remove(phba, ndlp);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_adisc_list,
|
||||
nlp_listp) {
|
||||
lpfc_nlp_remove(phba, ndlp);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_reglogin_list,
|
||||
nlp_listp) {
|
||||
lpfc_nlp_remove(phba, ndlp);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_prli_list,
|
||||
nlp_listp) {
|
||||
lpfc_nlp_remove(phba, ndlp);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_npr_list,
|
||||
nlp_listp) {
|
||||
lpfc_nlp_remove(phba, ndlp);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&phba->fc_nlpmap_list);
|
||||
INIT_LIST_HEAD(&phba->fc_nlpunmap_list);
|
||||
INIT_LIST_HEAD(&phba->fc_unused_list);
|
||||
INIT_LIST_HEAD(&phba->fc_plogi_list);
|
||||
INIT_LIST_HEAD(&phba->fc_adisc_list);
|
||||
INIT_LIST_HEAD(&phba->fc_reglogin_list);
|
||||
INIT_LIST_HEAD(&phba->fc_prli_list);
|
||||
INIT_LIST_HEAD(&phba->fc_npr_list);
|
||||
|
||||
phba->fc_map_cnt = 0;
|
||||
phba->fc_unmap_cnt = 0;
|
||||
phba->fc_plogi_cnt = 0;
|
||||
phba->fc_adisc_cnt = 0;
|
||||
phba->fc_reglogin_cnt = 0;
|
||||
phba->fc_prli_cnt = 0;
|
||||
phba->fc_npr_cnt = 0;
|
||||
phba->fc_unused_cnt= 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1262,21 +1206,6 @@ lpfc_stop_timer(struct lpfc_hba * phba)
|
|||
{
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
|
||||
/* Instead of a timer, this has been converted to a
|
||||
* deferred procedding list.
|
||||
*/
|
||||
while (!list_empty(&phba->freebufList)) {
|
||||
|
||||
struct lpfc_dmabuf *mp = NULL;
|
||||
|
||||
list_remove_head((&phba->freebufList), mp,
|
||||
struct lpfc_dmabuf, list);
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
}
|
||||
|
||||
del_timer_sync(&phba->fcp_poll_timer);
|
||||
del_timer_sync(&phba->fc_estabtmo);
|
||||
del_timer_sync(&phba->fc_disctmo);
|
||||
|
@ -1302,60 +1231,76 @@ lpfc_online(struct lpfc_hba * phba)
|
|||
"%d:0458 Bring Adapter online\n",
|
||||
phba->brd_no);
|
||||
|
||||
if (!lpfc_sli_queue_setup(phba))
|
||||
return 1;
|
||||
lpfc_block_mgmt_io(phba);
|
||||
|
||||
if (lpfc_sli_hba_setup(phba)) /* Initialize the HBA */
|
||||
if (!lpfc_sli_queue_setup(phba)) {
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (lpfc_sli_hba_setup(phba)) { /* Initialize the HBA */
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
return 1;
|
||||
}
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
phba->fc_flag &= ~FC_OFFLINE_MODE;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
lpfc_offline(struct lpfc_hba * phba)
|
||||
void
|
||||
lpfc_block_mgmt_io(struct lpfc_hba * phba)
|
||||
{
|
||||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_sli *psli;
|
||||
unsigned long iflag;
|
||||
int i;
|
||||
int cnt = 0;
|
||||
|
||||
if (!phba)
|
||||
return 0;
|
||||
spin_lock_irqsave(phba->host->host_lock, iflag);
|
||||
phba->fc_flag |= FC_BLOCK_MGMT_IO;
|
||||
spin_unlock_irqrestore(phba->host->host_lock, iflag);
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_unblock_mgmt_io(struct lpfc_hba * phba)
|
||||
{
|
||||
unsigned long iflag;
|
||||
|
||||
spin_lock_irqsave(phba->host->host_lock, iflag);
|
||||
phba->fc_flag &= ~FC_BLOCK_MGMT_IO;
|
||||
spin_unlock_irqrestore(phba->host->host_lock, iflag);
|
||||
}
|
||||
|
||||
void
|
||||
lpfc_offline_prep(struct lpfc_hba * phba)
|
||||
{
|
||||
struct lpfc_nodelist *ndlp, *next_ndlp;
|
||||
|
||||
if (phba->fc_flag & FC_OFFLINE_MODE)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
psli = &phba->sli;
|
||||
lpfc_block_mgmt_io(phba);
|
||||
|
||||
lpfc_linkdown(phba);
|
||||
|
||||
/* Issue an unreg_login to all nodes */
|
||||
list_for_each_entry_safe(ndlp, next_ndlp, &phba->fc_nodes, nlp_listp)
|
||||
if (ndlp->nlp_state != NLP_STE_UNUSED_NODE)
|
||||
lpfc_unreg_rpi(phba, ndlp);
|
||||
|
||||
lpfc_sli_flush_mbox_queue(phba);
|
||||
}
|
||||
|
||||
for (i = 0; i < psli->num_rings; i++) {
|
||||
pring = &psli->ring[i];
|
||||
/* The linkdown event takes 30 seconds to timeout. */
|
||||
while (pring->txcmplq_cnt) {
|
||||
mdelay(10);
|
||||
if (cnt++ > 3000) {
|
||||
lpfc_printf_log(phba,
|
||||
KERN_WARNING, LOG_INIT,
|
||||
"%d:0466 Outstanding IO when "
|
||||
"bringing Adapter offline\n",
|
||||
phba->brd_no);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void
|
||||
lpfc_offline(struct lpfc_hba * phba)
|
||||
{
|
||||
unsigned long iflag;
|
||||
|
||||
if (phba->fc_flag & FC_OFFLINE_MODE)
|
||||
return;
|
||||
|
||||
/* stop all timers associated with this hba */
|
||||
lpfc_stop_timer(phba);
|
||||
phba->work_hba_events = 0;
|
||||
phba->work_ha = 0;
|
||||
|
||||
lpfc_printf_log(phba,
|
||||
KERN_WARNING,
|
||||
|
@ -1366,11 +1311,12 @@ lpfc_offline(struct lpfc_hba * phba)
|
|||
/* Bring down the SLI Layer and cleanup. The HBA is offline
|
||||
now. */
|
||||
lpfc_sli_hba_down(phba);
|
||||
lpfc_cleanup(phba, 1);
|
||||
lpfc_cleanup(phba);
|
||||
spin_lock_irqsave(phba->host->host_lock, iflag);
|
||||
phba->work_hba_events = 0;
|
||||
phba->work_ha = 0;
|
||||
phba->fc_flag |= FC_OFFLINE_MODE;
|
||||
spin_unlock_irqrestore(phba->host->host_lock, iflag);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -1407,6 +1353,156 @@ lpfc_scsi_free(struct lpfc_hba * phba)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void lpfc_remove_device(struct lpfc_hba *phba)
|
||||
{
|
||||
unsigned long iflag;
|
||||
|
||||
lpfc_free_sysfs_attr(phba);
|
||||
|
||||
spin_lock_irqsave(phba->host->host_lock, iflag);
|
||||
phba->fc_flag |= FC_UNLOADING;
|
||||
|
||||
spin_unlock_irqrestore(phba->host->host_lock, iflag);
|
||||
|
||||
fc_remove_host(phba->host);
|
||||
scsi_remove_host(phba->host);
|
||||
|
||||
kthread_stop(phba->worker_thread);
|
||||
|
||||
/*
|
||||
* Bring down the SLI Layer. This step disable all interrupts,
|
||||
* clears the rings, discards all mailbox commands, and resets
|
||||
* the HBA.
|
||||
*/
|
||||
lpfc_sli_hba_down(phba);
|
||||
lpfc_sli_brdrestart(phba);
|
||||
|
||||
/* Release the irq reservation */
|
||||
free_irq(phba->pcidev->irq, phba);
|
||||
pci_disable_msi(phba->pcidev);
|
||||
|
||||
lpfc_cleanup(phba);
|
||||
lpfc_stop_timer(phba);
|
||||
phba->work_hba_events = 0;
|
||||
|
||||
/*
|
||||
* Call scsi_free before mem_free since scsi bufs are released to their
|
||||
* corresponding pools here.
|
||||
*/
|
||||
lpfc_scsi_free(phba);
|
||||
lpfc_mem_free(phba);
|
||||
|
||||
/* Free resources associated with SLI2 interface */
|
||||
dma_free_coherent(&phba->pcidev->dev, SLI2_SLIM_SIZE,
|
||||
phba->slim2p, phba->slim2p_mapping);
|
||||
|
||||
/* unmap adapter SLIM and Control Registers */
|
||||
iounmap(phba->ctrl_regs_memmap_p);
|
||||
iounmap(phba->slim_memmap_p);
|
||||
|
||||
pci_release_regions(phba->pcidev);
|
||||
pci_disable_device(phba->pcidev);
|
||||
|
||||
idr_remove(&lpfc_hba_index, phba->brd_no);
|
||||
scsi_host_put(phba->host);
|
||||
}
|
||||
|
||||
void lpfc_scan_start(struct Scsi_Host *host)
|
||||
{
|
||||
struct lpfc_hba *phba = (struct lpfc_hba*)host->hostdata;
|
||||
|
||||
if (lpfc_alloc_sysfs_attr(phba))
|
||||
goto error;
|
||||
|
||||
phba->MBslimaddr = phba->slim_memmap_p;
|
||||
phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
|
||||
phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
|
||||
phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
|
||||
phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
|
||||
|
||||
if (lpfc_sli_hba_setup(phba))
|
||||
goto error;
|
||||
|
||||
/*
|
||||
* hba setup may have changed the hba_queue_depth so we need to adjust
|
||||
* the value of can_queue.
|
||||
*/
|
||||
host->can_queue = phba->cfg_hba_queue_depth - 10;
|
||||
return;
|
||||
|
||||
error:
|
||||
lpfc_remove_device(phba);
|
||||
}
|
||||
|
||||
int lpfc_scan_finished(struct Scsi_Host *shost, unsigned long time)
|
||||
{
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
|
||||
|
||||
if (!phba->host)
|
||||
return 1;
|
||||
if (time >= 30 * HZ)
|
||||
goto finished;
|
||||
|
||||
if (phba->hba_state != LPFC_HBA_READY)
|
||||
return 0;
|
||||
if (phba->num_disc_nodes || phba->fc_prli_sent)
|
||||
return 0;
|
||||
if ((phba->fc_map_cnt == 0) && (time < 2 * HZ))
|
||||
return 0;
|
||||
if (phba->sli.sli_flag & LPFC_SLI_MBOX_ACTIVE)
|
||||
return 0;
|
||||
if ((phba->hba_state > LPFC_LINK_DOWN) || (time < 15 * HZ))
|
||||
return 0;
|
||||
|
||||
finished:
|
||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||
spin_lock_irq(shost->host_lock);
|
||||
lpfc_poll_start_timer(phba);
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* set fixed host attributes
|
||||
* Must done after lpfc_sli_hba_setup()
|
||||
*/
|
||||
|
||||
fc_host_node_name(shost) = wwn_to_u64(phba->fc_nodename.u.wwn);
|
||||
fc_host_port_name(shost) = wwn_to_u64(phba->fc_portname.u.wwn);
|
||||
fc_host_supported_classes(shost) = FC_COS_CLASS3;
|
||||
|
||||
memset(fc_host_supported_fc4s(shost), 0,
|
||||
sizeof(fc_host_supported_fc4s(shost)));
|
||||
fc_host_supported_fc4s(shost)[2] = 1;
|
||||
fc_host_supported_fc4s(shost)[7] = 1;
|
||||
|
||||
lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(shost));
|
||||
|
||||
fc_host_supported_speeds(shost) = 0;
|
||||
if (phba->lmt & LMT_10Gb)
|
||||
fc_host_supported_speeds(shost) |= FC_PORTSPEED_10GBIT;
|
||||
if (phba->lmt & LMT_4Gb)
|
||||
fc_host_supported_speeds(shost) |= FC_PORTSPEED_4GBIT;
|
||||
if (phba->lmt & LMT_2Gb)
|
||||
fc_host_supported_speeds(shost) |= FC_PORTSPEED_2GBIT;
|
||||
if (phba->lmt & LMT_1Gb)
|
||||
fc_host_supported_speeds(shost) |= FC_PORTSPEED_1GBIT;
|
||||
|
||||
fc_host_maxframe_size(shost) =
|
||||
((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
|
||||
(uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);
|
||||
|
||||
/* This value is also unchanging */
|
||||
memset(fc_host_active_fc4s(shost), 0,
|
||||
sizeof(fc_host_active_fc4s(shost)));
|
||||
fc_host_active_fc4s(shost)[2] = 1;
|
||||
fc_host_active_fc4s(shost)[7] = 1;
|
||||
|
||||
spin_lock_irq(shost->host_lock);
|
||||
phba->fc_flag &= ~FC_LOADING;
|
||||
spin_unlock_irq(shost->host_lock);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int __devinit
|
||||
lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
||||
|
@ -1445,9 +1541,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
goto out_put_host;
|
||||
|
||||
host->unique_id = phba->brd_no;
|
||||
INIT_LIST_HEAD(&phba->ctrspbuflist);
|
||||
INIT_LIST_HEAD(&phba->rnidrspbuflist);
|
||||
INIT_LIST_HEAD(&phba->freebufList);
|
||||
|
||||
/* Initialize timers used by driver */
|
||||
init_timer(&phba->fc_estabtmo);
|
||||
|
@ -1482,16 +1575,7 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
host->max_lun = phba->cfg_max_luns;
|
||||
host->this_id = -1;
|
||||
|
||||
/* Initialize all internally managed lists. */
|
||||
INIT_LIST_HEAD(&phba->fc_nlpmap_list);
|
||||
INIT_LIST_HEAD(&phba->fc_nlpunmap_list);
|
||||
INIT_LIST_HEAD(&phba->fc_unused_list);
|
||||
INIT_LIST_HEAD(&phba->fc_plogi_list);
|
||||
INIT_LIST_HEAD(&phba->fc_adisc_list);
|
||||
INIT_LIST_HEAD(&phba->fc_reglogin_list);
|
||||
INIT_LIST_HEAD(&phba->fc_prli_list);
|
||||
INIT_LIST_HEAD(&phba->fc_npr_list);
|
||||
|
||||
INIT_LIST_HEAD(&phba->fc_nodes);
|
||||
|
||||
pci_set_master(pdev);
|
||||
retval = pci_set_mwi(pdev);
|
||||
|
@ -1609,13 +1693,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
|
||||
host->transportt = lpfc_transport_template;
|
||||
pci_set_drvdata(pdev, host);
|
||||
error = scsi_add_host(host, &pdev->dev);
|
||||
if (error)
|
||||
goto out_kthread_stop;
|
||||
|
||||
error = lpfc_alloc_sysfs_attr(phba);
|
||||
if (error)
|
||||
goto out_remove_host;
|
||||
|
||||
if (phba->cfg_use_msi) {
|
||||
error = pci_enable_msi(phba->pcidev);
|
||||
|
@ -1631,73 +1708,15 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
|
||||
"%d:0451 Enable interrupt handler failed\n",
|
||||
phba->brd_no);
|
||||
goto out_free_sysfs_attr;
|
||||
goto out_kthread_stop;
|
||||
}
|
||||
phba->MBslimaddr = phba->slim_memmap_p;
|
||||
phba->HAregaddr = phba->ctrl_regs_memmap_p + HA_REG_OFFSET;
|
||||
phba->CAregaddr = phba->ctrl_regs_memmap_p + CA_REG_OFFSET;
|
||||
phba->HSregaddr = phba->ctrl_regs_memmap_p + HS_REG_OFFSET;
|
||||
phba->HCregaddr = phba->ctrl_regs_memmap_p + HC_REG_OFFSET;
|
||||
|
||||
error = lpfc_sli_hba_setup(phba);
|
||||
if (error) {
|
||||
error = -ENODEV;
|
||||
error = scsi_add_host(host, &pdev->dev);
|
||||
if (error)
|
||||
goto out_free_irq;
|
||||
}
|
||||
|
||||
/*
|
||||
* hba setup may have changed the hba_queue_depth so we need to adjust
|
||||
* the value of can_queue.
|
||||
*/
|
||||
host->can_queue = phba->cfg_hba_queue_depth - 10;
|
||||
scsi_scan_host(host);
|
||||
|
||||
lpfc_discovery_wait(phba);
|
||||
|
||||
if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
lpfc_poll_start_timer(phba);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* set fixed host attributes
|
||||
* Must done after lpfc_sli_hba_setup()
|
||||
*/
|
||||
|
||||
fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.u.wwn);
|
||||
fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.u.wwn);
|
||||
fc_host_supported_classes(host) = FC_COS_CLASS3;
|
||||
|
||||
memset(fc_host_supported_fc4s(host), 0,
|
||||
sizeof(fc_host_supported_fc4s(host)));
|
||||
fc_host_supported_fc4s(host)[2] = 1;
|
||||
fc_host_supported_fc4s(host)[7] = 1;
|
||||
|
||||
lpfc_get_hba_sym_node_name(phba, fc_host_symbolic_name(host));
|
||||
|
||||
fc_host_supported_speeds(host) = 0;
|
||||
if (phba->lmt & LMT_10Gb)
|
||||
fc_host_supported_speeds(host) |= FC_PORTSPEED_10GBIT;
|
||||
if (phba->lmt & LMT_4Gb)
|
||||
fc_host_supported_speeds(host) |= FC_PORTSPEED_4GBIT;
|
||||
if (phba->lmt & LMT_2Gb)
|
||||
fc_host_supported_speeds(host) |= FC_PORTSPEED_2GBIT;
|
||||
if (phba->lmt & LMT_1Gb)
|
||||
fc_host_supported_speeds(host) |= FC_PORTSPEED_1GBIT;
|
||||
|
||||
fc_host_maxframe_size(host) =
|
||||
((((uint32_t) phba->fc_sparam.cmn.bbRcvSizeMsb & 0x0F) << 8) |
|
||||
(uint32_t) phba->fc_sparam.cmn.bbRcvSizeLsb);
|
||||
|
||||
/* This value is also unchanging */
|
||||
memset(fc_host_active_fc4s(host), 0,
|
||||
sizeof(fc_host_active_fc4s(host)));
|
||||
fc_host_active_fc4s(host)[2] = 1;
|
||||
fc_host_active_fc4s(host)[7] = 1;
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
phba->fc_flag &= ~FC_LOADING;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return 0;
|
||||
|
||||
out_free_irq:
|
||||
|
@ -1705,11 +1724,6 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid)
|
|||
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:
|
||||
fc_remove_host(phba->host);
|
||||
scsi_remove_host(phba->host);
|
||||
out_kthread_stop:
|
||||
kthread_stop(phba->worker_thread);
|
||||
out_free_iocbq:
|
||||
|
@ -1747,56 +1761,8 @@ lpfc_pci_remove_one(struct pci_dev *pdev)
|
|||
{
|
||||
struct Scsi_Host *host = pci_get_drvdata(pdev);
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *)host->hostdata;
|
||||
unsigned long iflag;
|
||||
|
||||
lpfc_free_sysfs_attr(phba);
|
||||
|
||||
spin_lock_irqsave(phba->host->host_lock, iflag);
|
||||
phba->fc_flag |= FC_UNLOADING;
|
||||
|
||||
spin_unlock_irqrestore(phba->host->host_lock, iflag);
|
||||
|
||||
fc_remove_host(phba->host);
|
||||
scsi_remove_host(phba->host);
|
||||
|
||||
kthread_stop(phba->worker_thread);
|
||||
|
||||
/*
|
||||
* Bring down the SLI Layer. This step disable all interrupts,
|
||||
* clears the rings, discards all mailbox commands, and resets
|
||||
* the HBA.
|
||||
*/
|
||||
lpfc_sli_hba_down(phba);
|
||||
lpfc_sli_brdrestart(phba);
|
||||
|
||||
/* Release the irq reservation */
|
||||
free_irq(phba->pcidev->irq, phba);
|
||||
pci_disable_msi(phba->pcidev);
|
||||
|
||||
lpfc_cleanup(phba, 0);
|
||||
lpfc_stop_timer(phba);
|
||||
phba->work_hba_events = 0;
|
||||
|
||||
/*
|
||||
* Call scsi_free before mem_free since scsi bufs are released to their
|
||||
* corresponding pools here.
|
||||
*/
|
||||
lpfc_scsi_free(phba);
|
||||
lpfc_mem_free(phba);
|
||||
|
||||
/* Free resources associated with SLI2 interface */
|
||||
dma_free_coherent(&pdev->dev, SLI2_SLIM_SIZE,
|
||||
phba->slim2p, phba->slim2p_mapping);
|
||||
|
||||
/* unmap adapter SLIM and Control Registers */
|
||||
iounmap(phba->ctrl_regs_memmap_p);
|
||||
iounmap(phba->slim_memmap_p);
|
||||
|
||||
pci_release_regions(phba->pcidev);
|
||||
pci_disable_device(phba->pcidev);
|
||||
|
||||
idr_remove(&lpfc_hba_index, phba->brd_no);
|
||||
scsi_host_put(phba->host);
|
||||
lpfc_remove_device(phba);
|
||||
|
||||
pci_set_drvdata(pdev, NULL);
|
||||
}
|
||||
|
@ -1941,6 +1907,18 @@ static struct pci_device_id lpfc_id_table[] = {
|
|||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LPE11000S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_MID,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SMB,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_DCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_SCSP,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SAT_S,
|
||||
PCI_ANY_ID, PCI_ANY_ID, },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||
|
@ -212,6 +212,7 @@ lpfc_init_link(struct lpfc_hba * phba,
|
|||
case LINK_SPEED_1G:
|
||||
case LINK_SPEED_2G:
|
||||
case LINK_SPEED_4G:
|
||||
case LINK_SPEED_8G:
|
||||
mb->un.varInitLnk.link_flags |=
|
||||
FLAGS_LINK_SPEED;
|
||||
mb->un.varInitLnk.link_speed = linkspeed;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||
|
@ -168,14 +168,13 @@ lpfc_check_elscmpl_iocb(struct lpfc_hba * phba,
|
|||
* routine effectively results in a "software abort".
|
||||
*/
|
||||
int
|
||||
lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
|
||||
int send_abts)
|
||||
lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp)
|
||||
{
|
||||
LIST_HEAD(completions);
|
||||
struct lpfc_sli *psli;
|
||||
struct lpfc_sli_ring *pring;
|
||||
struct lpfc_iocbq *iocb, *next_iocb;
|
||||
IOCB_t *icmd;
|
||||
int found = 0;
|
||||
IOCB_t *cmd;
|
||||
|
||||
/* Abort outstanding I/O on NPort <nlp_DID> */
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_DISCOVERY,
|
||||
|
@ -188,75 +187,39 @@ lpfc_els_abort(struct lpfc_hba * phba, struct lpfc_nodelist * ndlp,
|
|||
pring = &psli->ring[LPFC_ELS_RING];
|
||||
|
||||
/* First check the txq */
|
||||
do {
|
||||
found = 0;
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
|
||||
/* Check to see if iocb matches the nport we are looking
|
||||
for */
|
||||
if ((lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))) {
|
||||
found = 1;
|
||||
/* It matches, so deque and call compl with an
|
||||
error */
|
||||
list_del(&iocb->list);
|
||||
pring->txq_cnt--;
|
||||
if (iocb->iocb_cmpl) {
|
||||
icmd = &iocb->iocb;
|
||||
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
} else
|
||||
lpfc_sli_release_iocbq(phba, iocb);
|
||||
break;
|
||||
}
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
|
||||
/* Check to see if iocb matches the nport we are looking
|
||||
for */
|
||||
if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp)) {
|
||||
/* It matches, so deque and call compl with an
|
||||
error */
|
||||
list_move_tail(&iocb->list, &completions);
|
||||
pring->txq_cnt--;
|
||||
}
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
} while (found);
|
||||
}
|
||||
|
||||
/* Everything on txcmplq will be returned by firmware
|
||||
* with a no rpi / linkdown / abort error. For ring 0,
|
||||
* ELS discovery, we want to get rid of it right here.
|
||||
*/
|
||||
/* Next check the txcmplq */
|
||||
do {
|
||||
found = 0;
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq,
|
||||
list) {
|
||||
/* Check to see if iocb matches the nport we are looking
|
||||
for */
|
||||
if ((lpfc_check_sli_ndlp (phba, pring, iocb, ndlp))) {
|
||||
found = 1;
|
||||
/* It matches, so deque and call compl with an
|
||||
error */
|
||||
list_del(&iocb->list);
|
||||
pring->txcmplq_cnt--;
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
|
||||
/* Check to see if iocb matches the nport we are looking
|
||||
for */
|
||||
if (lpfc_check_sli_ndlp(phba, pring, iocb, ndlp))
|
||||
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
|
||||
}
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
icmd = &iocb->iocb;
|
||||
/* If the driver is completing an ELS
|
||||
* command early, flush it out of the firmware.
|
||||
*/
|
||||
if (send_abts &&
|
||||
(icmd->ulpCommand == CMD_ELS_REQUEST64_CR) &&
|
||||
(icmd->un.elsreq64.bdl.ulpIoTag32)) {
|
||||
lpfc_sli_issue_abort_iotag32(phba,
|
||||
pring, iocb);
|
||||
}
|
||||
if (iocb->iocb_cmpl) {
|
||||
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
} else
|
||||
lpfc_sli_release_iocbq(phba, iocb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
} while(found);
|
||||
while (!list_empty(&completions)) {
|
||||
iocb = list_get_first(&completions, struct lpfc_iocbq, list);
|
||||
cmd = &iocb->iocb;
|
||||
list_del(&iocb->list);
|
||||
|
||||
if (iocb->iocb_cmpl) {
|
||||
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
|
||||
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||
} else
|
||||
lpfc_sli_release_iocbq(phba, iocb);
|
||||
}
|
||||
|
||||
/* If we are delaying issuing an ELS command, cancel it */
|
||||
if (ndlp->nlp_flag & NLP_DELAY_TMO)
|
||||
|
@ -390,7 +353,10 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
|
|||
* queue this mbox command to be processed later.
|
||||
*/
|
||||
mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
|
||||
mbox->context2 = ndlp;
|
||||
/*
|
||||
* mbox->context2 = lpfc_nlp_get(ndlp) deferred until mailbox
|
||||
* command issued in lpfc_cmpl_els_acc().
|
||||
*/
|
||||
ndlp->nlp_flag |= (NLP_ACC_REGLOGIN | NLP_RCV_PLOGI);
|
||||
|
||||
/*
|
||||
|
@ -404,7 +370,7 @@ lpfc_rcv_plogi(struct lpfc_hba * phba,
|
|||
*/
|
||||
if (ndlp->nlp_state == NLP_STE_PLOGI_ISSUE) {
|
||||
/* software abort outstanding PLOGI */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
}
|
||||
|
||||
lpfc_els_rsp_acc(phba, ELS_CMD_PLOGI, cmdiocb, ndlp, mbox, 0);
|
||||
|
@ -471,8 +437,7 @@ lpfc_rcv_padisc(struct lpfc_hba * phba,
|
|||
spin_unlock_irq(phba->host->host_lock);
|
||||
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
|
||||
ndlp->nlp_prev_state = ndlp->nlp_state;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -502,12 +467,10 @@ lpfc_rcv_logo(struct lpfc_hba * phba,
|
|||
|
||||
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
|
||||
ndlp->nlp_prev_state = ndlp->nlp_state;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
} else {
|
||||
ndlp->nlp_prev_state = ndlp->nlp_state;
|
||||
ndlp->nlp_state = NLP_STE_UNUSED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
|
||||
}
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
|
@ -601,11 +564,10 @@ lpfc_rcv_plogi_unused_node(struct lpfc_hba * phba,
|
|||
|
||||
if (lpfc_rcv_plogi(phba, ndlp, cmdiocb)) {
|
||||
ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
|
||||
ndlp->nlp_state = NLP_STE_UNUSED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
|
||||
|
@ -614,7 +576,7 @@ lpfc_rcv_els_unused_node(struct lpfc_hba * phba,
|
|||
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
|
||||
{
|
||||
lpfc_issue_els_logo(phba, ndlp, 0);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
||||
|
@ -630,7 +592,7 @@ lpfc_rcv_logo_unused_node(struct lpfc_hba * phba,
|
|||
ndlp->nlp_flag |= NLP_LOGO_ACC;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
|
||||
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
@ -639,7 +601,7 @@ static uint32_t
|
|||
lpfc_cmpl_logo_unused_node(struct lpfc_hba * phba,
|
||||
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
|
||||
{
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
|
||||
|
@ -647,7 +609,7 @@ static uint32_t
|
|||
lpfc_device_rm_unused_node(struct lpfc_hba * phba,
|
||||
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
|
||||
{
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
|
||||
|
@ -697,7 +659,7 @@ lpfc_rcv_logo_plogi_issue(struct lpfc_hba * phba,
|
|||
cmdiocb = (struct lpfc_iocbq *) arg;
|
||||
|
||||
/* software abort outstanding PLOGI */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
|
||||
return ndlp->nlp_state;
|
||||
|
@ -712,7 +674,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,
|
|||
cmdiocb = (struct lpfc_iocbq *) arg;
|
||||
|
||||
/* software abort outstanding PLOGI */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
if (evt == NLP_EVT_RCV_LOGO) {
|
||||
lpfc_els_rsp_acc(phba, ELS_CMD_ACC, cmdiocb, ndlp, NULL, 0);
|
||||
|
@ -727,8 +689,7 @@ lpfc_rcv_els_plogi_issue(struct lpfc_hba * phba,
|
|||
spin_unlock_irq(phba->host->host_lock);
|
||||
ndlp->nlp_last_elscmd = ELS_CMD_PLOGI;
|
||||
ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
@ -803,32 +764,26 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
|
|||
goto out;
|
||||
|
||||
lpfc_unreg_rpi(phba, ndlp);
|
||||
if (lpfc_reg_login
|
||||
(phba, irsp->un.elsreq64.remoteID,
|
||||
(uint8_t *) sp, mbox, 0) == 0) {
|
||||
if (lpfc_reg_login(phba, irsp->un.elsreq64.remoteID, (uint8_t *) sp,
|
||||
mbox, 0) == 0) {
|
||||
switch (ndlp->nlp_DID) {
|
||||
case NameServer_DID:
|
||||
mbox->mbox_cmpl =
|
||||
lpfc_mbx_cmpl_ns_reg_login;
|
||||
mbox->mbox_cmpl = lpfc_mbx_cmpl_ns_reg_login;
|
||||
break;
|
||||
case FDMI_DID:
|
||||
mbox->mbox_cmpl =
|
||||
lpfc_mbx_cmpl_fdmi_reg_login;
|
||||
mbox->mbox_cmpl = lpfc_mbx_cmpl_fdmi_reg_login;
|
||||
break;
|
||||
default:
|
||||
mbox->mbox_cmpl =
|
||||
lpfc_mbx_cmpl_reg_login;
|
||||
mbox->mbox_cmpl = lpfc_mbx_cmpl_reg_login;
|
||||
}
|
||||
mbox->context2 = ndlp;
|
||||
mbox->context2 = lpfc_nlp_get(ndlp);
|
||||
if (lpfc_sli_issue_mbox(phba, mbox,
|
||||
(MBX_NOWAIT | MBX_STOP_IOCB))
|
||||
!= MBX_NOT_FINISHED) {
|
||||
ndlp->nlp_state =
|
||||
NLP_STE_REG_LOGIN_ISSUE;
|
||||
lpfc_nlp_list(phba, ndlp,
|
||||
NLP_REGLOGIN_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_REG_LOGIN_ISSUE);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
lpfc_nlp_put(ndlp);
|
||||
mp = (struct lpfc_dmabuf *)mbox->context1;
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
|
@ -841,7 +796,7 @@ lpfc_cmpl_plogi_plogi_issue(struct lpfc_hba * phba,
|
|||
out:
|
||||
/* Free this node since the driver cannot login or has the wrong
|
||||
sparm */
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
|
||||
|
@ -855,9 +810,9 @@ lpfc_device_rm_plogi_issue(struct lpfc_hba * phba,
|
|||
}
|
||||
else {
|
||||
/* software abort outstanding PLOGI */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
}
|
||||
|
@ -868,11 +823,10 @@ lpfc_device_recov_plogi_issue(struct lpfc_hba * phba,
|
|||
uint32_t evt)
|
||||
{
|
||||
/* software abort outstanding PLOGI */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
ndlp->nlp_prev_state = NLP_STE_PLOGI_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
@ -888,7 +842,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
|
|||
struct lpfc_iocbq *cmdiocb;
|
||||
|
||||
/* software abort outstanding ADISC */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
cmdiocb = (struct lpfc_iocbq *) arg;
|
||||
|
||||
|
@ -896,8 +850,7 @@ lpfc_rcv_plogi_adisc_issue(struct lpfc_hba * phba,
|
|||
return ndlp->nlp_state;
|
||||
}
|
||||
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
|
||||
lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
|
||||
|
||||
return ndlp->nlp_state;
|
||||
|
@ -926,7 +879,7 @@ lpfc_rcv_logo_adisc_issue(struct lpfc_hba * phba,
|
|||
cmdiocb = (struct lpfc_iocbq *) arg;
|
||||
|
||||
/* software abort outstanding ADISC */
|
||||
lpfc_els_abort(phba, ndlp, 0);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
|
||||
return ndlp->nlp_state;
|
||||
|
@ -987,20 +940,17 @@ lpfc_cmpl_adisc_adisc_issue(struct lpfc_hba * phba,
|
|||
memset(&ndlp->nlp_portname, 0, sizeof (struct lpfc_name));
|
||||
|
||||
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
lpfc_unreg_rpi(phba, ndlp);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
||||
if (ndlp->nlp_type & NLP_FCP_TARGET) {
|
||||
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_MAPPED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
|
||||
} else {
|
||||
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
|
||||
}
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
@ -1016,9 +966,9 @@ lpfc_device_rm_adisc_issue(struct lpfc_hba * phba,
|
|||
}
|
||||
else {
|
||||
/* software abort outstanding ADISC */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
}
|
||||
|
@ -1029,11 +979,10 @@ lpfc_device_recov_adisc_issue(struct lpfc_hba * phba,
|
|||
uint32_t evt)
|
||||
{
|
||||
/* software abort outstanding ADISC */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
ndlp->nlp_prev_state = NLP_STE_ADISC_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
|
||||
ndlp->nlp_flag |= NLP_NPR_ADISC;
|
||||
|
@ -1074,9 +1023,36 @@ lpfc_rcv_logo_reglogin_issue(struct lpfc_hba * phba,
|
|||
uint32_t evt)
|
||||
{
|
||||
struct lpfc_iocbq *cmdiocb;
|
||||
LPFC_MBOXQ_t *mb;
|
||||
LPFC_MBOXQ_t *nextmb;
|
||||
struct lpfc_dmabuf *mp;
|
||||
|
||||
cmdiocb = (struct lpfc_iocbq *) arg;
|
||||
|
||||
/* cleanup any ndlp on mbox q waiting for reglogin cmpl */
|
||||
if ((mb = phba->sli.mbox_active)) {
|
||||
if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
|
||||
(ndlp == (struct lpfc_nodelist *) mb->context2)) {
|
||||
mb->context2 = NULL;
|
||||
mb->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
list_for_each_entry_safe(mb, nextmb, &phba->sli.mboxq, list) {
|
||||
if ((mb->mb.mbxCommand == MBX_REG_LOGIN64) &&
|
||||
(ndlp == (struct lpfc_nodelist *) mb->context2)) {
|
||||
mp = (struct lpfc_dmabuf *) (mb->context1);
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
list_del(&mb->list);
|
||||
mempool_free(mb, phba->mbox_mem_pool);
|
||||
}
|
||||
}
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
@ -1133,8 +1109,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
|
|||
*/
|
||||
if (mb->mbxStatus == MBXERR_RPI_FULL) {
|
||||
ndlp->nlp_prev_state = NLP_STE_UNUSED_NODE;
|
||||
ndlp->nlp_state = NLP_STE_UNUSED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNUSED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNUSED_NODE);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
||||
|
@ -1147,8 +1122,7 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
|
|||
|
||||
lpfc_issue_els_logo(phba, ndlp, 0);
|
||||
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
||||
|
@ -1157,13 +1131,11 @@ lpfc_cmpl_reglogin_reglogin_issue(struct lpfc_hba * phba,
|
|||
/* Only if we are not a fabric nport do we issue PRLI */
|
||||
if (!(ndlp->nlp_type & NLP_FABRIC)) {
|
||||
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_PRLI_ISSUE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_PRLI_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PRLI_ISSUE);
|
||||
lpfc_issue_els_prli(phba, ndlp, 0);
|
||||
} else {
|
||||
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
|
||||
}
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
@ -1178,7 +1150,7 @@ lpfc_device_rm_reglogin_issue(struct lpfc_hba * phba,
|
|||
return ndlp->nlp_state;
|
||||
}
|
||||
else {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
}
|
||||
|
@ -1189,8 +1161,7 @@ lpfc_device_recov_reglogin_issue(struct lpfc_hba * phba,
|
|||
uint32_t evt)
|
||||
{
|
||||
ndlp->nlp_prev_state = NLP_STE_REG_LOGIN_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
@ -1230,7 +1201,7 @@ lpfc_rcv_logo_prli_issue(struct lpfc_hba * phba,
|
|||
cmdiocb = (struct lpfc_iocbq *) arg;
|
||||
|
||||
/* Software abort outstanding PRLI before sending acc */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
lpfc_rcv_logo(phba, ndlp, cmdiocb, ELS_CMD_LOGO);
|
||||
return ndlp->nlp_state;
|
||||
|
@ -1279,8 +1250,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
|
|||
irsp = &rspiocb->iocb;
|
||||
if (irsp->ulpStatus) {
|
||||
ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_UNMAPPED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_UNMAPPED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_UNMAPPED_NODE);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
||||
|
@ -1298,8 +1268,7 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_hba * phba,
|
|||
}
|
||||
|
||||
ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_MAPPED_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_MAPPED_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_MAPPED_NODE);
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
||||
|
@ -1330,9 +1299,9 @@ lpfc_device_rm_prli_issue(struct lpfc_hba * phba,
|
|||
}
|
||||
else {
|
||||
/* software abort outstanding PLOGI */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
}
|
||||
|
@ -1359,11 +1328,10 @@ lpfc_device_recov_prli_issue(struct lpfc_hba * phba,
|
|||
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
|
||||
{
|
||||
/* software abort outstanding PRLI */
|
||||
lpfc_els_abort(phba, ndlp, 1);
|
||||
lpfc_els_abort(phba, ndlp);
|
||||
|
||||
ndlp->nlp_prev_state = NLP_STE_PRLI_ISSUE;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
@ -1436,8 +1404,7 @@ lpfc_device_recov_unmap_node(struct lpfc_hba * phba,
|
|||
struct lpfc_nodelist * ndlp, void *arg, uint32_t evt)
|
||||
{
|
||||
ndlp->nlp_prev_state = NLP_STE_UNMAPPED_NODE;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
|
||||
lpfc_disc_set_adisc(phba, ndlp);
|
||||
|
||||
|
@ -1518,8 +1485,7 @@ lpfc_device_recov_mapped_node(struct lpfc_hba * phba,
|
|||
uint32_t evt)
|
||||
{
|
||||
ndlp->nlp_prev_state = NLP_STE_MAPPED_NODE;
|
||||
ndlp->nlp_state = NLP_STE_NPR_NODE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NPR_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_NPR_NODE);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
ndlp->nlp_flag &= ~(NLP_NODEV_REMOVE | NLP_NPR_2B_DISC);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
@ -1551,8 +1517,7 @@ lpfc_rcv_plogi_npr_node(struct lpfc_hba * phba,
|
|||
/* send PLOGI immediately, move to PLOGI issue state */
|
||||
if (!(ndlp->nlp_flag & NLP_DELAY_TMO)) {
|
||||
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
|
||||
ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
|
||||
lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
|
||||
}
|
||||
|
||||
|
@ -1580,16 +1545,13 @@ lpfc_rcv_prli_npr_node(struct lpfc_hba * phba,
|
|||
ndlp->nlp_flag &= ~NLP_NPR_ADISC;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
|
||||
ndlp->nlp_state = NLP_STE_ADISC_ISSUE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
|
||||
lpfc_issue_els_adisc(phba, ndlp, 0);
|
||||
} else {
|
||||
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
|
||||
ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
|
||||
lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
|
||||
}
|
||||
|
||||
}
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
|
@ -1627,13 +1589,11 @@ lpfc_rcv_padisc_npr_node(struct lpfc_hba * phba,
|
|||
!(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;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_ADISC_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_ADISC_ISSUE);
|
||||
lpfc_issue_els_adisc(phba, ndlp, 0);
|
||||
} else {
|
||||
ndlp->nlp_prev_state = NLP_STE_NPR_NODE;
|
||||
ndlp->nlp_state = NLP_STE_PLOGI_ISSUE;
|
||||
lpfc_nlp_list(phba, ndlp, NLP_PLOGI_LIST);
|
||||
lpfc_nlp_set_state(phba, ndlp, NLP_STE_PLOGI_ISSUE);
|
||||
lpfc_issue_els_plogi(phba, ndlp->nlp_DID, 0);
|
||||
}
|
||||
}
|
||||
|
@ -1682,7 +1642,7 @@ lpfc_cmpl_plogi_npr_node(struct lpfc_hba * phba,
|
|||
|
||||
irsp = &rspiocb->iocb;
|
||||
if (irsp->ulpStatus) {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
return ndlp->nlp_state;
|
||||
|
@ -1700,7 +1660,7 @@ lpfc_cmpl_prli_npr_node(struct lpfc_hba * phba,
|
|||
|
||||
irsp = &rspiocb->iocb;
|
||||
if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
return ndlp->nlp_state;
|
||||
|
@ -1728,7 +1688,7 @@ lpfc_cmpl_adisc_npr_node(struct lpfc_hba * phba,
|
|||
|
||||
irsp = &rspiocb->iocb;
|
||||
if (irsp->ulpStatus && (ndlp->nlp_flag & NLP_NODEV_REMOVE)) {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
return ndlp->nlp_state;
|
||||
|
@ -1749,7 +1709,7 @@ lpfc_cmpl_reglogin_npr_node(struct lpfc_hba * phba,
|
|||
ndlp->nlp_rpi = mb->un.varWords[0];
|
||||
else {
|
||||
if (ndlp->nlp_flag & NLP_NODEV_REMOVE) {
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
}
|
||||
|
@ -1765,7 +1725,7 @@ lpfc_device_rm_npr_node(struct lpfc_hba * phba,
|
|||
ndlp->nlp_flag |= NLP_NODEV_REMOVE;
|
||||
return ndlp->nlp_state;
|
||||
}
|
||||
lpfc_nlp_list(phba, ndlp, NLP_NO_LIST);
|
||||
lpfc_drop_node(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
|
||||
|
@ -1964,7 +1924,7 @@ lpfc_disc_state_machine(struct lpfc_hba * phba,
|
|||
uint32_t(*func) (struct lpfc_hba *, struct lpfc_nodelist *, void *,
|
||||
uint32_t);
|
||||
|
||||
ndlp->nlp_disc_refcnt++;
|
||||
lpfc_nlp_get(ndlp);
|
||||
cur_state = ndlp->nlp_state;
|
||||
|
||||
/* DSM in event <evt> on NPort <nlp_DID> in state <cur_state> */
|
||||
|
@ -1987,18 +1947,7 @@ lpfc_disc_state_machine(struct lpfc_hba * phba,
|
|||
phba->brd_no,
|
||||
rc, ndlp->nlp_DID, ndlp->nlp_flag);
|
||||
|
||||
ndlp->nlp_disc_refcnt--;
|
||||
lpfc_nlp_put(ndlp);
|
||||
|
||||
/* Check to see if ndlp removal is deferred */
|
||||
if ((ndlp->nlp_disc_refcnt == 0)
|
||||
&& (ndlp->nlp_flag & NLP_DELAY_REMOVE)) {
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
ndlp->nlp_flag &= ~NLP_DELAY_REMOVE;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
lpfc_nlp_remove(phba, ndlp);
|
||||
return NLP_STE_FREED_NODE;
|
||||
}
|
||||
if (rc == NLP_STE_FREED_NODE)
|
||||
return NLP_STE_FREED_NODE;
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||
|
@ -146,6 +146,10 @@ lpfc_get_scsi_buf(struct lpfc_hba * phba)
|
|||
|
||||
spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
|
||||
list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
|
||||
if (lpfc_cmd) {
|
||||
lpfc_cmd->seg_cnt = 0;
|
||||
lpfc_cmd->nonsg_phys = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
|
||||
return lpfc_cmd;
|
||||
}
|
||||
|
@ -288,13 +292,13 @@ lpfc_scsi_unprep_dma_buf(struct lpfc_hba * phba, struct lpfc_scsi_buf * psb)
|
|||
}
|
||||
|
||||
static void
|
||||
lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
||||
lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd, struct lpfc_iocbq *rsp_iocb)
|
||||
{
|
||||
struct scsi_cmnd *cmnd = lpfc_cmd->pCmd;
|
||||
struct fcp_cmnd *fcpcmd = lpfc_cmd->fcp_cmnd;
|
||||
struct fcp_rsp *fcprsp = lpfc_cmd->fcp_rsp;
|
||||
struct lpfc_hba *phba = lpfc_cmd->scsi_hba;
|
||||
uint32_t fcpi_parm = lpfc_cmd->cur_iocbq.iocb.un.fcpi.fcpi_parm;
|
||||
uint32_t fcpi_parm = rsp_iocb->iocb.un.fcpi.fcpi_parm;
|
||||
uint32_t resp_info = fcprsp->rspStatus2;
|
||||
uint32_t scsi_status = fcprsp->rspStatus3;
|
||||
uint32_t *lp;
|
||||
|
@ -355,6 +359,24 @@ lpfc_handle_fcp_err(struct lpfc_scsi_buf *lpfc_cmd)
|
|||
be32_to_cpu(fcpcmd->fcpDl), cmnd->resid,
|
||||
fcpi_parm, cmnd->cmnd[0], cmnd->underflow);
|
||||
|
||||
/*
|
||||
* If there is an under run check if under run reported by
|
||||
* storage array is same as the under run reported by HBA.
|
||||
* If this is not same, there is a dropped frame.
|
||||
*/
|
||||
if ((cmnd->sc_data_direction == DMA_FROM_DEVICE) &&
|
||||
fcpi_parm &&
|
||||
(cmnd->resid != fcpi_parm)) {
|
||||
lpfc_printf_log(phba, KERN_WARNING,
|
||||
LOG_FCP | LOG_FCP_ERROR,
|
||||
"%d:0735 FCP Read Check Error and Underrun "
|
||||
"Data: x%x x%x x%x x%x\n", phba->brd_no,
|
||||
be32_to_cpu(fcpcmd->fcpDl),
|
||||
cmnd->resid,
|
||||
fcpi_parm, cmnd->cmnd[0]);
|
||||
cmnd->resid = cmnd->request_bufflen;
|
||||
host_status = DID_ERROR;
|
||||
}
|
||||
/*
|
||||
* The cmnd->underflow is the minimum number of bytes that must
|
||||
* be transfered for this command. Provided a sense condition
|
||||
|
@ -435,7 +457,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
switch (lpfc_cmd->status) {
|
||||
case IOSTAT_FCP_RSP_ERROR:
|
||||
/* Call FCP RSP handler to determine result */
|
||||
lpfc_handle_fcp_err(lpfc_cmd);
|
||||
lpfc_handle_fcp_err(lpfc_cmd,pIocbOut);
|
||||
break;
|
||||
case IOSTAT_NPORT_BSY:
|
||||
case IOSTAT_FABRIC_BSY:
|
||||
|
@ -466,10 +488,10 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
|
||||
result = cmd->result;
|
||||
sdev = cmd->device;
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
cmd->scsi_done(cmd);
|
||||
|
||||
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
return;
|
||||
}
|
||||
|
@ -527,7 +549,6 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn,
|
|||
}
|
||||
}
|
||||
|
||||
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
}
|
||||
|
||||
|
@ -670,6 +691,18 @@ lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_hba *phba,
|
|||
return (1);
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_tskmgmt_def_cmpl(struct lpfc_hba *phba,
|
||||
struct lpfc_iocbq *cmdiocbq,
|
||||
struct lpfc_iocbq *rspiocbq)
|
||||
{
|
||||
struct lpfc_scsi_buf *lpfc_cmd =
|
||||
(struct lpfc_scsi_buf *) cmdiocbq->context1;
|
||||
if (lpfc_cmd)
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
static int
|
||||
lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
|
||||
unsigned tgt_id, unsigned int lun,
|
||||
|
@ -706,8 +739,9 @@ lpfc_scsi_tgt_reset(struct lpfc_scsi_buf * lpfc_cmd, struct lpfc_hba * phba,
|
|||
&phba->sli.ring[phba->sli.fcp_ring],
|
||||
iocbq, iocbqrsp, lpfc_cmd->timeout);
|
||||
if (ret != IOCB_SUCCESS) {
|
||||
if (ret == IOCB_TIMEDOUT)
|
||||
iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
|
||||
lpfc_cmd->status = IOSTAT_DRIVER_REJECT;
|
||||
ret = FAILED;
|
||||
} else {
|
||||
ret = SUCCESS;
|
||||
lpfc_cmd->result = iocbqrsp->iocb.un.ulpWord[4];
|
||||
|
@ -974,7 +1008,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
|
|||
}
|
||||
|
||||
static int
|
||||
lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
||||
lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
|
||||
{
|
||||
struct Scsi_Host *shost = cmnd->device->host;
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
|
||||
|
@ -984,6 +1018,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
struct lpfc_nodelist *pnode = rdata->pnode;
|
||||
uint32_t cmd_result = 0, cmd_status = 0;
|
||||
int ret = FAILED;
|
||||
int iocb_status = IOCB_SUCCESS;
|
||||
int cnt, loopcnt;
|
||||
|
||||
lpfc_block_error_handler(cmnd);
|
||||
|
@ -995,7 +1030,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
*/
|
||||
while ( 1 ) {
|
||||
if (!pnode)
|
||||
return FAILED;
|
||||
goto out;
|
||||
|
||||
if (pnode->nlp_state != NLP_STE_MAPPED_NODE) {
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
@ -1013,7 +1048,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
}
|
||||
pnode = rdata->pnode;
|
||||
if (!pnode)
|
||||
return FAILED;
|
||||
goto out;
|
||||
}
|
||||
if (pnode->nlp_state == NLP_STE_MAPPED_NODE)
|
||||
break;
|
||||
|
@ -1028,7 +1063,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
lpfc_cmd->rdata = rdata;
|
||||
|
||||
ret = lpfc_scsi_prep_task_mgmt_cmd(phba, lpfc_cmd, cmnd->device->lun,
|
||||
FCP_LUN_RESET);
|
||||
FCP_TARGET_RESET);
|
||||
if (!ret)
|
||||
goto out_free_scsi_buf;
|
||||
|
||||
|
@ -1040,16 +1075,21 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
goto out_free_scsi_buf;
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_FCP,
|
||||
"%d:0703 Issue LUN Reset to TGT %d LUN %d "
|
||||
"Data: x%x x%x\n", phba->brd_no, cmnd->device->id,
|
||||
"%d:0703 Issue target reset to TGT %d LUN %d rpi x%x "
|
||||
"nlp_flag x%x\n", phba->brd_no, cmnd->device->id,
|
||||
cmnd->device->lun, pnode->nlp_rpi, pnode->nlp_flag);
|
||||
|
||||
ret = lpfc_sli_issue_iocb_wait(phba,
|
||||
iocb_status = lpfc_sli_issue_iocb_wait(phba,
|
||||
&phba->sli.ring[phba->sli.fcp_ring],
|
||||
iocbq, iocbqrsp, lpfc_cmd->timeout);
|
||||
if (ret == IOCB_SUCCESS)
|
||||
ret = SUCCESS;
|
||||
|
||||
if (iocb_status == IOCB_TIMEDOUT)
|
||||
iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl;
|
||||
|
||||
if (iocb_status == IOCB_SUCCESS)
|
||||
ret = SUCCESS;
|
||||
else
|
||||
ret = iocb_status;
|
||||
|
||||
cmd_result = iocbqrsp->iocb.un.ulpWord[4];
|
||||
cmd_status = iocbqrsp->iocb.ulpStatus;
|
||||
|
@ -1087,18 +1127,19 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
|
||||
if (cnt) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
||||
"%d:0719 LUN Reset I/O flush failure: cnt x%x\n",
|
||||
"%d:0719 device reset I/O flush failure: cnt x%x\n",
|
||||
phba->brd_no, cnt);
|
||||
ret = FAILED;
|
||||
}
|
||||
|
||||
out_free_scsi_buf:
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
|
||||
if (iocb_status != IOCB_TIMEDOUT) {
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
}
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_FCP,
|
||||
"%d:0713 SCSI layer issued LUN reset (%d, %d) "
|
||||
"Data: x%x x%x x%x\n",
|
||||
phba->brd_no, cmnd->device->id,cmnd->device->lun,
|
||||
"%d:0713 SCSI layer issued device reset (%d, %d) "
|
||||
"return x%x status x%x result x%x\n",
|
||||
phba->brd_no, cmnd->device->id, cmnd->device->lun,
|
||||
ret, cmd_status, cmd_result);
|
||||
|
||||
out:
|
||||
|
@ -1107,7 +1148,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
|
|||
}
|
||||
|
||||
static int
|
||||
lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
||||
lpfc_bus_reset_handler(struct scsi_cmnd *cmnd)
|
||||
{
|
||||
struct Scsi_Host *shost = cmnd->device->host;
|
||||
struct lpfc_hba *phba = (struct lpfc_hba *)shost->hostdata;
|
||||
|
@ -1134,10 +1175,12 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|||
* fail, this routine returns failure to the midlayer.
|
||||
*/
|
||||
for (i = 0; i < LPFC_MAX_TARGET; i++) {
|
||||
/* Search the mapped list for this target ID */
|
||||
/* Search for mapped node by target ID */
|
||||
match = 0;
|
||||
list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {
|
||||
if ((i == ndlp->nlp_sid) && ndlp->rport) {
|
||||
list_for_each_entry(ndlp, &phba->fc_nodes, nlp_listp) {
|
||||
if (ndlp->nlp_state == NLP_STE_MAPPED_NODE &&
|
||||
i == ndlp->nlp_sid &&
|
||||
ndlp->rport) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -1152,13 +1195,17 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
|
|||
"%d:0700 Bus Reset on target %d failed\n",
|
||||
phba->brd_no, i);
|
||||
err_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != IOCB_TIMEDOUT)
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
|
||||
if (err_count == 0)
|
||||
ret = SUCCESS;
|
||||
|
||||
lpfc_release_scsi_buf(phba, lpfc_cmd);
|
||||
else
|
||||
ret = FAILED;
|
||||
|
||||
/*
|
||||
* All outstanding txcmplq I/Os should have been aborted by
|
||||
|
@ -1299,11 +1346,13 @@ struct scsi_host_template lpfc_template = {
|
|||
.info = lpfc_info,
|
||||
.queuecommand = lpfc_queuecommand,
|
||||
.eh_abort_handler = lpfc_abort_handler,
|
||||
.eh_device_reset_handler= lpfc_reset_lun_handler,
|
||||
.eh_bus_reset_handler = lpfc_reset_bus_handler,
|
||||
.eh_device_reset_handler= lpfc_device_reset_handler,
|
||||
.eh_bus_reset_handler = lpfc_bus_reset_handler,
|
||||
.slave_alloc = lpfc_slave_alloc,
|
||||
.slave_configure = lpfc_slave_configure,
|
||||
.slave_destroy = lpfc_slave_destroy,
|
||||
.scan_finished = lpfc_scan_finished,
|
||||
.scan_start = lpfc_scan_start,
|
||||
.this_id = -1,
|
||||
.sg_tablesize = LPFC_SG_SEG_CNT,
|
||||
.cmd_per_lun = LPFC_CMD_PER_LUN,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* Portions Copyright (C) 2004-2005 Christoph Hellwig *
|
||||
|
@ -528,6 +528,7 @@ lpfc_sli_wake_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq)
|
|||
* If pdone_q is empty, the driver thread gave up waiting and
|
||||
* continued running.
|
||||
*/
|
||||
pmboxq->mbox_flag |= LPFC_MBX_WAKE;
|
||||
pdone_q = (wait_queue_head_t *) pmboxq->context1;
|
||||
if (pdone_q)
|
||||
wake_up_interruptible(pdone_q);
|
||||
|
@ -538,11 +539,32 @@ void
|
|||
lpfc_sli_def_mbox_cmpl(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmb)
|
||||
{
|
||||
struct lpfc_dmabuf *mp;
|
||||
uint16_t rpi;
|
||||
int rc;
|
||||
|
||||
mp = (struct lpfc_dmabuf *) (pmb->context1);
|
||||
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt, mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
|
||||
/*
|
||||
* If a REG_LOGIN succeeded after node is destroyed or node
|
||||
* is in re-discovery driver need to cleanup the RPI.
|
||||
*/
|
||||
if (!(phba->fc_flag & FC_UNLOADING) &&
|
||||
(pmb->mb.mbxCommand == MBX_REG_LOGIN64) &&
|
||||
(!pmb->mb.mbxStatus)) {
|
||||
|
||||
rpi = pmb->mb.un.varWords[0];
|
||||
lpfc_unreg_login(phba, rpi, pmb);
|
||||
pmb->mbox_cmpl=lpfc_sli_def_mbox_cmpl;
|
||||
rc = lpfc_sli_issue_mbox(phba, pmb, MBX_NOWAIT);
|
||||
if (rc != MBX_NOT_FINISHED)
|
||||
return;
|
||||
}
|
||||
|
||||
mempool_free( pmb, phba->mbox_mem_pool);
|
||||
return;
|
||||
}
|
||||
|
@ -693,25 +715,8 @@ lpfc_sli_handle_mb_event(struct lpfc_hba * phba)
|
|||
} else {
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
/* Turn on IOCB processing */
|
||||
for (i = 0; i < phba->sli.num_rings; i++) {
|
||||
for (i = 0; i < phba->sli.num_rings; i++)
|
||||
lpfc_sli_turn_on_ring(phba, i);
|
||||
}
|
||||
|
||||
/* Free any lpfc_dmabuf's waiting for mbox cmd cmpls */
|
||||
while (!list_empty(&phba->freebufList)) {
|
||||
struct lpfc_dmabuf *mp;
|
||||
|
||||
mp = NULL;
|
||||
list_remove_head((&phba->freebufList),
|
||||
mp,
|
||||
struct lpfc_dmabuf,
|
||||
list);
|
||||
if (mp) {
|
||||
lpfc_mbuf_free(phba, mp->virt,
|
||||
mp->phys);
|
||||
kfree(mp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (process_next);
|
||||
|
@ -833,6 +838,14 @@ lpfc_sli_process_sol_iocb(struct lpfc_hba * phba, struct lpfc_sli_ring * pring,
|
|||
* All other are passed to the completion callback.
|
||||
*/
|
||||
if (pring->ringno == LPFC_ELS_RING) {
|
||||
if (cmdiocbp->iocb_flag & LPFC_DRIVER_ABORTED) {
|
||||
cmdiocbp->iocb_flag &=
|
||||
~LPFC_DRIVER_ABORTED;
|
||||
saveq->iocb.ulpStatus =
|
||||
IOSTAT_LOCAL_REJECT;
|
||||
saveq->iocb.un.ulpWord[4] =
|
||||
IOERR_SLI_ABORTED;
|
||||
}
|
||||
spin_unlock_irqrestore(phba->host->host_lock,
|
||||
iflag);
|
||||
(cmdiocbp->iocb_cmpl) (phba, cmdiocbp, saveq);
|
||||
|
@ -1464,8 +1477,9 @@ lpfc_sli_handle_slow_ring_event(struct lpfc_hba * phba,
|
|||
int
|
||||
lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
|
||||
{
|
||||
LIST_HEAD(completions);
|
||||
struct lpfc_iocbq *iocb, *next_iocb;
|
||||
IOCB_t *icmd = NULL, *cmd = NULL;
|
||||
IOCB_t *cmd = NULL;
|
||||
int errcnt;
|
||||
|
||||
errcnt = 0;
|
||||
|
@ -1474,46 +1488,28 @@ lpfc_sli_abort_iocb_ring(struct lpfc_hba *phba, struct lpfc_sli_ring *pring)
|
|||
* First do the txq.
|
||||
*/
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
|
||||
list_del_init(&iocb->list);
|
||||
if (iocb->iocb_cmpl) {
|
||||
icmd = &iocb->iocb;
|
||||
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
} else
|
||||
lpfc_sli_release_iocbq(phba, iocb);
|
||||
}
|
||||
list_splice_init(&pring->txq, &completions);
|
||||
pring->txq_cnt = 0;
|
||||
INIT_LIST_HEAD(&(pring->txq));
|
||||
|
||||
/* Next issue ABTS for everything on the txcmplq */
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list) {
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txcmplq, list)
|
||||
lpfc_sli_issue_abort_iotag(phba, pring, iocb);
|
||||
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
while (!list_empty(&completions)) {
|
||||
iocb = list_get_first(&completions, struct lpfc_iocbq, list);
|
||||
cmd = &iocb->iocb;
|
||||
|
||||
/*
|
||||
* Imediate abort of IOCB, deque and call compl
|
||||
*/
|
||||
|
||||
list_del_init(&iocb->list);
|
||||
pring->txcmplq_cnt--;
|
||||
list_del(&iocb->list);
|
||||
|
||||
if (iocb->iocb_cmpl) {
|
||||
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
} else
|
||||
lpfc_sli_release_iocbq(phba, iocb);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&pring->txcmplq);
|
||||
pring->txcmplq_cnt = 0;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
return errcnt;
|
||||
}
|
||||
|
||||
|
@ -1588,6 +1584,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
|
|||
hc_copy = readl(phba->HCregaddr);
|
||||
writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
|
||||
readl(phba->HCregaddr); /* flush */
|
||||
phba->fc_flag |= FC_IGNORE_ERATT;
|
||||
|
||||
if (readl(phba->HAregaddr) & HA_ERATT) {
|
||||
/* Clear Chip error bit */
|
||||
|
@ -1630,6 +1627,7 @@ void lpfc_reset_barrier(struct lpfc_hba * phba)
|
|||
}
|
||||
|
||||
restore_hc:
|
||||
phba->fc_flag &= ~FC_IGNORE_ERATT;
|
||||
writel(hc_copy, phba->HCregaddr);
|
||||
readl(phba->HCregaddr); /* flush */
|
||||
}
|
||||
|
@ -1665,6 +1663,7 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
|
|||
status &= ~HC_ERINT_ENA;
|
||||
writel(status, phba->HCregaddr);
|
||||
readl(phba->HCregaddr); /* flush */
|
||||
phba->fc_flag |= FC_IGNORE_ERATT;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
lpfc_kill_board(phba, pmb);
|
||||
|
@ -1674,6 +1673,9 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
|
|||
if (retval != MBX_SUCCESS) {
|
||||
if (retval != MBX_BUSY)
|
||||
mempool_free(pmb, phba->mbox_mem_pool);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
phba->fc_flag &= ~FC_IGNORE_ERATT;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1700,6 +1702,7 @@ lpfc_sli_brdkill(struct lpfc_hba * phba)
|
|||
}
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
psli->sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
|
||||
phba->fc_flag &= ~FC_IGNORE_ERATT;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
|
||||
psli->mbox_active = NULL;
|
||||
|
@ -1985,42 +1988,6 @@ lpfc_sli_hba_setup(struct lpfc_hba * phba)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static void
|
||||
lpfc_mbox_abort(struct lpfc_hba * phba)
|
||||
{
|
||||
LPFC_MBOXQ_t *pmbox;
|
||||
MAILBOX_t *mb;
|
||||
|
||||
if (phba->sli.mbox_active) {
|
||||
del_timer_sync(&phba->sli.mbox_tmo);
|
||||
phba->work_hba_events &= ~WORKER_MBOX_TMO;
|
||||
pmbox = phba->sli.mbox_active;
|
||||
mb = &pmbox->mb;
|
||||
phba->sli.mbox_active = NULL;
|
||||
if (pmbox->mbox_cmpl) {
|
||||
mb->mbxStatus = MBX_NOT_FINISHED;
|
||||
(pmbox->mbox_cmpl) (phba, pmbox);
|
||||
}
|
||||
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
|
||||
}
|
||||
|
||||
/* Abort all the non active mailbox commands. */
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
pmbox = lpfc_mbox_get(phba);
|
||||
while (pmbox) {
|
||||
mb = &pmbox->mb;
|
||||
if (pmbox->mbox_cmpl) {
|
||||
mb->mbxStatus = MBX_NOT_FINISHED;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
(pmbox->mbox_cmpl) (phba, pmbox);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
}
|
||||
pmbox = lpfc_mbox_get(phba);
|
||||
}
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*! lpfc_mbox_timeout
|
||||
*
|
||||
* \pre
|
||||
|
@ -2055,6 +2022,8 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
|
|||
{
|
||||
LPFC_MBOXQ_t *pmbox;
|
||||
MAILBOX_t *mb;
|
||||
struct lpfc_sli *psli = &phba->sli;
|
||||
struct lpfc_sli_ring *pring;
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
if (!(phba->work_hba_events & WORKER_MBOX_TMO)) {
|
||||
|
@ -2062,8 +2031,6 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
|
|||
return;
|
||||
}
|
||||
|
||||
phba->work_hba_events &= ~WORKER_MBOX_TMO;
|
||||
|
||||
pmbox = phba->sli.mbox_active;
|
||||
mb = &pmbox->mb;
|
||||
|
||||
|
@ -2078,17 +2045,32 @@ lpfc_mbox_timeout_handler(struct lpfc_hba *phba)
|
|||
phba->sli.sli_flag,
|
||||
phba->sli.mbox_active);
|
||||
|
||||
phba->sli.mbox_active = NULL;
|
||||
if (pmbox->mbox_cmpl) {
|
||||
mb->mbxStatus = MBX_NOT_FINISHED;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
(pmbox->mbox_cmpl) (phba, pmbox);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
}
|
||||
phba->sli.sli_flag &= ~LPFC_SLI_MBOX_ACTIVE;
|
||||
|
||||
/* Setting state unknown so lpfc_sli_abort_iocb_ring
|
||||
* would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
|
||||
* it to fail all oustanding SCSI IO.
|
||||
*/
|
||||
phba->hba_state = LPFC_STATE_UNKNOWN;
|
||||
phba->work_hba_events &= ~WORKER_MBOX_TMO;
|
||||
phba->fc_flag |= FC_ESTABLISH_LINK;
|
||||
psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
lpfc_mbox_abort(phba);
|
||||
|
||||
pring = &psli->ring[psli->fcp_ring];
|
||||
lpfc_sli_abort_iocb_ring(phba, pring);
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
|
||||
"%d:0316 Resetting board due to mailbox timeout\n",
|
||||
phba->brd_no);
|
||||
/*
|
||||
* lpfc_offline calls lpfc_sli_hba_down which will clean up
|
||||
* on oustanding mailbox commands.
|
||||
*/
|
||||
lpfc_offline_prep(phba);
|
||||
lpfc_offline(phba);
|
||||
lpfc_sli_brdrestart(phba);
|
||||
if (lpfc_online(phba) == 0) /* Initialize the HBA */
|
||||
mod_timer(&phba->fc_estabtmo, jiffies + HZ * 60);
|
||||
lpfc_unblock_mgmt_io(phba);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2320,9 +2302,7 @@ lpfc_sli_issue_mbox(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmbox, uint32_t flag)
|
|||
spin_unlock_irqrestore(phba->host->host_lock,
|
||||
drvr_flag);
|
||||
|
||||
/* Can be in interrupt context, do not sleep */
|
||||
/* (or might be called with interrupts disabled) */
|
||||
mdelay(1);
|
||||
msleep(1);
|
||||
|
||||
spin_lock_irqsave(phba->host->host_lock, drvr_flag);
|
||||
|
||||
|
@ -2430,7 +2410,7 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
|
||||
if (unlikely(phba->hba_state == LPFC_LINK_DOWN)) {
|
||||
/*
|
||||
* Only CREATE_XRI, CLOSE_XRI, ABORT_XRI, and QUE_RING_BUF
|
||||
* Only CREATE_XRI, CLOSE_XRI, and QUE_RING_BUF
|
||||
* can be issued if the link is not up.
|
||||
*/
|
||||
switch (piocb->iocb.ulpCommand) {
|
||||
|
@ -2444,6 +2424,8 @@ lpfc_sli_issue_iocb(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
piocb->iocb_cmpl = NULL;
|
||||
/*FALLTHROUGH*/
|
||||
case CMD_CREATE_XRI_CR:
|
||||
case CMD_CLOSE_XRI_CN:
|
||||
case CMD_CLOSE_XRI_CX:
|
||||
break;
|
||||
default:
|
||||
goto iocb_busy;
|
||||
|
@ -2637,11 +2619,12 @@ lpfc_sli_queue_setup(struct lpfc_hba * phba)
|
|||
int
|
||||
lpfc_sli_hba_down(struct lpfc_hba * phba)
|
||||
{
|
||||
LIST_HEAD(completions);
|
||||
struct lpfc_sli *psli;
|
||||
struct lpfc_sli_ring *pring;
|
||||
LPFC_MBOXQ_t *pmb;
|
||||
struct lpfc_iocbq *iocb, *next_iocb;
|
||||
IOCB_t *icmd = NULL;
|
||||
struct lpfc_iocbq *iocb;
|
||||
IOCB_t *cmd = NULL;
|
||||
int i;
|
||||
unsigned long flags = 0;
|
||||
|
||||
|
@ -2649,7 +2632,6 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
|
|||
lpfc_hba_down_prep(phba);
|
||||
|
||||
spin_lock_irqsave(phba->host->host_lock, flags);
|
||||
|
||||
for (i = 0; i < psli->num_rings; i++) {
|
||||
pring = &psli->ring[i];
|
||||
pring->flag |= LPFC_DEFERRED_RING_EVENT;
|
||||
|
@ -2658,28 +2640,25 @@ lpfc_sli_hba_down(struct lpfc_hba * phba)
|
|||
* Error everything on the txq since these iocbs have not been
|
||||
* given to the FW yet.
|
||||
*/
|
||||
list_splice_init(&pring->txq, &completions);
|
||||
pring->txq_cnt = 0;
|
||||
|
||||
list_for_each_entry_safe(iocb, next_iocb, &pring->txq, list) {
|
||||
list_del_init(&iocb->list);
|
||||
if (iocb->iocb_cmpl) {
|
||||
icmd = &iocb->iocb;
|
||||
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
icmd->un.ulpWord[4] = IOERR_SLI_DOWN;
|
||||
spin_unlock_irqrestore(phba->host->host_lock,
|
||||
flags);
|
||||
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||
spin_lock_irqsave(phba->host->host_lock, flags);
|
||||
} else
|
||||
lpfc_sli_release_iocbq(phba, iocb);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&(pring->txq));
|
||||
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(phba->host->host_lock, flags);
|
||||
|
||||
while (!list_empty(&completions)) {
|
||||
iocb = list_get_first(&completions, struct lpfc_iocbq, list);
|
||||
cmd = &iocb->iocb;
|
||||
list_del(&iocb->list);
|
||||
|
||||
if (iocb->iocb_cmpl) {
|
||||
cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
|
||||
(iocb->iocb_cmpl) (phba, iocb, iocb);
|
||||
} else
|
||||
lpfc_sli_release_iocbq(phba, iocb);
|
||||
}
|
||||
|
||||
/* Return any active mbox cmds */
|
||||
del_timer_sync(&psli->mbox_tmo);
|
||||
spin_lock_irqsave(phba->host->host_lock, flags);
|
||||
|
@ -2768,85 +2747,138 @@ lpfc_sli_ringpostbuf_get(struct lpfc_hba *phba, struct lpfc_sli_ring *pring,
|
|||
}
|
||||
|
||||
static void
|
||||
lpfc_sli_abort_elsreq_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
struct lpfc_iocbq * rspiocb)
|
||||
lpfc_sli_abort_els_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
struct lpfc_iocbq * rspiocb)
|
||||
{
|
||||
struct lpfc_dmabuf *buf_ptr, *buf_ptr1;
|
||||
/* Free the resources associated with the ELS_REQUEST64 IOCB the driver
|
||||
* just aborted.
|
||||
* In this case, context2 = cmd, context2->next = rsp, context3 = bpl
|
||||
*/
|
||||
if (cmdiocb->context2) {
|
||||
buf_ptr1 = (struct lpfc_dmabuf *) cmdiocb->context2;
|
||||
IOCB_t *irsp;
|
||||
uint16_t abort_iotag, abort_context;
|
||||
struct lpfc_iocbq *abort_iocb, *rsp_ab_iocb;
|
||||
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
|
||||
|
||||
/* Free the response IOCB before completing the abort
|
||||
command. */
|
||||
buf_ptr = NULL;
|
||||
list_remove_head((&buf_ptr1->list), buf_ptr,
|
||||
struct lpfc_dmabuf, list);
|
||||
if (buf_ptr) {
|
||||
lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
|
||||
kfree(buf_ptr);
|
||||
abort_iocb = NULL;
|
||||
irsp = &rspiocb->iocb;
|
||||
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
|
||||
if (irsp->ulpStatus) {
|
||||
abort_context = cmdiocb->iocb.un.acxri.abortContextTag;
|
||||
abort_iotag = cmdiocb->iocb.un.acxri.abortIoTag;
|
||||
|
||||
if (abort_iotag != 0 && abort_iotag <= phba->sli.last_iotag)
|
||||
abort_iocb = phba->sli.iocbq_lookup[abort_iotag];
|
||||
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"%d:0327 Cannot abort els iocb %p"
|
||||
" with tag %x context %x\n",
|
||||
phba->brd_no, abort_iocb,
|
||||
abort_iotag, abort_context);
|
||||
|
||||
/*
|
||||
* make sure we have the right iocbq before taking it
|
||||
* off the txcmplq and try to call completion routine.
|
||||
*/
|
||||
if (abort_iocb &&
|
||||
abort_iocb->iocb.ulpContext == abort_context &&
|
||||
abort_iocb->iocb_flag & LPFC_DRIVER_ABORTED) {
|
||||
list_del(&abort_iocb->list);
|
||||
pring->txcmplq_cnt--;
|
||||
|
||||
rsp_ab_iocb = lpfc_sli_get_iocbq(phba);
|
||||
if (rsp_ab_iocb == NULL)
|
||||
lpfc_sli_release_iocbq(phba, abort_iocb);
|
||||
else {
|
||||
abort_iocb->iocb_flag &=
|
||||
~LPFC_DRIVER_ABORTED;
|
||||
rsp_ab_iocb->iocb.ulpStatus =
|
||||
IOSTAT_LOCAL_REJECT;
|
||||
rsp_ab_iocb->iocb.un.ulpWord[4] =
|
||||
IOERR_SLI_ABORTED;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
(abort_iocb->iocb_cmpl)
|
||||
(phba, abort_iocb, rsp_ab_iocb);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
lpfc_sli_release_iocbq(phba, rsp_ab_iocb);
|
||||
}
|
||||
}
|
||||
lpfc_mbuf_free(phba, buf_ptr1->virt, buf_ptr1->phys);
|
||||
kfree(buf_ptr1);
|
||||
}
|
||||
|
||||
if (cmdiocb->context3) {
|
||||
buf_ptr = (struct lpfc_dmabuf *) cmdiocb->context3;
|
||||
lpfc_mbuf_free(phba, buf_ptr->virt, buf_ptr->phys);
|
||||
kfree(buf_ptr);
|
||||
}
|
||||
|
||||
lpfc_sli_release_iocbq(phba, cmdiocb);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
int
|
||||
lpfc_sli_issue_abort_iotag32(struct lpfc_hba * phba,
|
||||
struct lpfc_sli_ring * pring,
|
||||
struct lpfc_iocbq * cmdiocb)
|
||||
lpfc_sli_issue_abort_iotag(struct lpfc_hba * phba,
|
||||
struct lpfc_sli_ring * pring,
|
||||
struct lpfc_iocbq * cmdiocb)
|
||||
{
|
||||
struct lpfc_iocbq *abtsiocbp;
|
||||
IOCB_t *icmd = NULL;
|
||||
IOCB_t *iabt = NULL;
|
||||
int retval = IOCB_ERROR;
|
||||
|
||||
/* There are certain command types we don't want
|
||||
* to abort.
|
||||
*/
|
||||
icmd = &cmdiocb->iocb;
|
||||
if ((icmd->ulpCommand == CMD_ABORT_XRI_CN) ||
|
||||
(icmd->ulpCommand == CMD_CLOSE_XRI_CN))
|
||||
return 0;
|
||||
|
||||
/* If we're unloading, interrupts are disabled so we
|
||||
* need to cleanup the iocb here.
|
||||
*/
|
||||
if (phba->fc_flag & FC_UNLOADING)
|
||||
goto abort_iotag_exit;
|
||||
|
||||
/* issue ABTS for this IOCB based on iotag */
|
||||
abtsiocbp = lpfc_sli_get_iocbq(phba);
|
||||
if (abtsiocbp == NULL)
|
||||
return 0;
|
||||
|
||||
/* This signals the response to set the correct status
|
||||
* before calling the completion handler.
|
||||
*/
|
||||
cmdiocb->iocb_flag |= LPFC_DRIVER_ABORTED;
|
||||
|
||||
iabt = &abtsiocbp->iocb;
|
||||
icmd = &cmdiocb->iocb;
|
||||
switch (icmd->ulpCommand) {
|
||||
case CMD_ELS_REQUEST64_CR:
|
||||
/* Even though we abort the ELS command, the firmware may access
|
||||
* the BPL or other resources before it processes our
|
||||
* ABORT_MXRI64. Thus we must delay reusing the cmdiocb
|
||||
* resources till the actual abort request completes.
|
||||
*/
|
||||
abtsiocbp->context1 = (void *)((unsigned long)icmd->ulpCommand);
|
||||
abtsiocbp->context2 = cmdiocb->context2;
|
||||
abtsiocbp->context3 = cmdiocb->context3;
|
||||
cmdiocb->context2 = NULL;
|
||||
cmdiocb->context3 = NULL;
|
||||
abtsiocbp->iocb_cmpl = lpfc_sli_abort_elsreq_cmpl;
|
||||
break;
|
||||
default:
|
||||
lpfc_sli_release_iocbq(phba, abtsiocbp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iabt->un.amxri.abortType = ABORT_TYPE_ABTS;
|
||||
iabt->un.amxri.iotag32 = icmd->un.elsreq64.bdl.ulpIoTag32;
|
||||
|
||||
iabt->un.acxri.abortType = ABORT_TYPE_ABTS;
|
||||
iabt->un.acxri.abortContextTag = icmd->ulpContext;
|
||||
iabt->un.acxri.abortIoTag = icmd->ulpIoTag;
|
||||
iabt->ulpLe = 1;
|
||||
iabt->ulpClass = CLASS3;
|
||||
iabt->ulpCommand = CMD_ABORT_MXRI64_CN;
|
||||
iabt->ulpClass = icmd->ulpClass;
|
||||
|
||||
if (lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0) == IOCB_ERROR) {
|
||||
lpfc_sli_release_iocbq(phba, abtsiocbp);
|
||||
return 0;
|
||||
if (phba->hba_state >= LPFC_LINK_UP)
|
||||
iabt->ulpCommand = CMD_ABORT_XRI_CN;
|
||||
else
|
||||
iabt->ulpCommand = CMD_CLOSE_XRI_CN;
|
||||
|
||||
abtsiocbp->iocb_cmpl = lpfc_sli_abort_els_cmpl;
|
||||
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
"%d:0339 Abort xri x%x, original iotag x%x, abort "
|
||||
"cmd iotag x%x\n",
|
||||
phba->brd_no, iabt->un.acxri.abortContextTag,
|
||||
iabt->un.acxri.abortIoTag, abtsiocbp->iotag);
|
||||
retval = lpfc_sli_issue_iocb(phba, pring, abtsiocbp, 0);
|
||||
|
||||
abort_iotag_exit:
|
||||
|
||||
/* If we could not issue an abort dequeue the iocb and handle
|
||||
* the completion here.
|
||||
*/
|
||||
if (retval == IOCB_ERROR) {
|
||||
list_del(&cmdiocb->list);
|
||||
pring->txcmplq_cnt--;
|
||||
|
||||
if (cmdiocb->iocb_cmpl) {
|
||||
icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
|
||||
icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
(cmdiocb->iocb_cmpl) (phba, cmdiocb, cmdiocb);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
} else
|
||||
lpfc_sli_release_iocbq(phba, cmdiocb);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
@ -2918,9 +2950,11 @@ void
|
|||
lpfc_sli_abort_fcp_cmpl(struct lpfc_hba * phba, struct lpfc_iocbq * cmdiocb,
|
||||
struct lpfc_iocbq * rspiocb)
|
||||
{
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
unsigned long iflags;
|
||||
|
||||
spin_lock_irqsave(phba->host->host_lock, iflags);
|
||||
lpfc_sli_release_iocbq(phba, cmdiocb);
|
||||
spin_unlock_irq(phba->host->host_lock);
|
||||
spin_unlock_irqrestore(phba->host->host_lock, iflags);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3043,22 +3077,22 @@ lpfc_sli_issue_iocb_wait(struct lpfc_hba * phba,
|
|||
timeout_req);
|
||||
spin_lock_irq(phba->host->host_lock);
|
||||
|
||||
if (timeleft == 0) {
|
||||
if (piocb->iocb_flag & LPFC_IO_WAKE) {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
"%d:0331 IOCB wake signaled\n",
|
||||
phba->brd_no);
|
||||
} else if (timeleft == 0) {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"%d:0338 IOCB wait timeout error - no "
|
||||
"wake response Data x%x\n",
|
||||
phba->brd_no, timeout);
|
||||
retval = IOCB_TIMEDOUT;
|
||||
} else if (!(piocb->iocb_flag & LPFC_IO_WAKE)) {
|
||||
} else {
|
||||
lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
|
||||
"%d:0330 IOCB wake NOT set, "
|
||||
"Data x%x x%lx\n", phba->brd_no,
|
||||
timeout, (timeleft / jiffies));
|
||||
retval = IOCB_TIMEDOUT;
|
||||
} else {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
"%d:0331 IOCB wake signaled\n",
|
||||
phba->brd_no);
|
||||
}
|
||||
} else {
|
||||
lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
|
||||
|
@ -3087,8 +3121,6 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
|
|||
uint32_t timeout)
|
||||
{
|
||||
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q);
|
||||
DECLARE_WAITQUEUE(wq_entry, current);
|
||||
uint32_t timeleft = 0;
|
||||
int retval;
|
||||
|
||||
/* The caller must leave context1 empty. */
|
||||
|
@ -3101,27 +3133,25 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba * phba, LPFC_MBOXQ_t * pmboxq,
|
|||
/* setup context field to pass wait_queue pointer to wake function */
|
||||
pmboxq->context1 = &done_q;
|
||||
|
||||
/* start to sleep before we wait, to avoid races */
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
add_wait_queue(&done_q, &wq_entry);
|
||||
|
||||
/* now issue the command */
|
||||
retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT);
|
||||
|
||||
if (retval == MBX_BUSY || retval == MBX_SUCCESS) {
|
||||
timeleft = schedule_timeout(timeout * HZ);
|
||||
wait_event_interruptible_timeout(done_q,
|
||||
pmboxq->mbox_flag & LPFC_MBX_WAKE,
|
||||
timeout * HZ);
|
||||
|
||||
pmboxq->context1 = NULL;
|
||||
/* if schedule_timeout returns 0, we timed out and were not
|
||||
woken up */
|
||||
if ((timeleft == 0) || signal_pending(current))
|
||||
retval = MBX_TIMEOUT;
|
||||
else
|
||||
/*
|
||||
* if LPFC_MBX_WAKE flag is set the mailbox is completed
|
||||
* else do not free the resources.
|
||||
*/
|
||||
if (pmboxq->mbox_flag & LPFC_MBX_WAKE)
|
||||
retval = MBX_SUCCESS;
|
||||
else
|
||||
retval = MBX_TIMEOUT;
|
||||
}
|
||||
|
||||
|
||||
set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&done_q, &wq_entry);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -3184,6 +3214,11 @@ lpfc_intr_handler(int irq, void *dev_id)
|
|||
*/
|
||||
spin_lock(phba->host->host_lock);
|
||||
ha_copy = readl(phba->HAregaddr);
|
||||
/* If somebody is waiting to handle an eratt don't process it
|
||||
* here. The brdkill function will do this.
|
||||
*/
|
||||
if (phba->fc_flag & FC_IGNORE_ERATT)
|
||||
ha_copy &= ~HA_ERATT;
|
||||
writel((ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
|
||||
readl(phba->HAregaddr); /* flush */
|
||||
spin_unlock(phba->host->host_lock);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -39,9 +39,10 @@ struct lpfc_iocbq {
|
|||
IOCB_t iocb; /* IOCB cmd */
|
||||
uint8_t retry; /* retry counter for IOCB cmd - if needed */
|
||||
uint8_t iocb_flag;
|
||||
#define LPFC_IO_LIBDFC 1 /* libdfc iocb */
|
||||
#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */
|
||||
#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */
|
||||
#define LPFC_IO_LIBDFC 1 /* libdfc iocb */
|
||||
#define LPFC_IO_WAKE 2 /* High Priority Queue signal flag */
|
||||
#define LPFC_IO_FCP 4 /* FCP command -- iocbq in scsi_buf */
|
||||
#define LPFC_DRIVER_ABORTED 8 /* driver aborted this request */
|
||||
|
||||
uint8_t abort_count;
|
||||
uint8_t rsvd2;
|
||||
|
@ -67,6 +68,8 @@ struct lpfc_iocbq {
|
|||
#define IOCB_ERROR 2
|
||||
#define IOCB_TIMEDOUT 3
|
||||
|
||||
#define LPFC_MBX_WAKE 1
|
||||
|
||||
typedef struct lpfcMboxq {
|
||||
/* MBOXQs are used in single linked lists */
|
||||
struct list_head list; /* ptr to next mailbox command */
|
||||
|
@ -75,6 +78,7 @@ typedef struct lpfcMboxq {
|
|||
void *context2; /* caller context information */
|
||||
|
||||
void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *);
|
||||
uint8_t mbox_flag;
|
||||
|
||||
} LPFC_MBOXQ_t;
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*******************************************************************
|
||||
* This file is part of the Emulex Linux Device Driver for *
|
||||
* Fibre Channel Host Bus Adapters. *
|
||||
* Copyright (C) 2004-2006 Emulex. All rights reserved. *
|
||||
* Copyright (C) 2004-2007 Emulex. All rights reserved. *
|
||||
* EMULEX and SLI are trademarks of Emulex. *
|
||||
* www.emulex.com *
|
||||
* *
|
||||
|
@ -18,12 +18,12 @@
|
|||
* included with this package. *
|
||||
*******************************************************************/
|
||||
|
||||
#define LPFC_DRIVER_VERSION "8.1.11"
|
||||
#define LPFC_DRIVER_VERSION "8.1.12"
|
||||
|
||||
#define LPFC_DRIVER_NAME "lpfc"
|
||||
|
||||
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
|
||||
LPFC_DRIVER_VERSION
|
||||
#define LPFC_COPYRIGHT "Copyright(c) 2004-2006 Emulex. All rights reserved."
|
||||
#define LPFC_COPYRIGHT "Copyright(c) 2004-2007 Emulex. All rights reserved."
|
||||
|
||||
#define DFC_API_VERSION "0.0.0"
|
||||
|
|
|
@ -1754,7 +1754,8 @@ __mega_busywait_mbox (adapter_t *adapter)
|
|||
for (counter = 0; counter < 10000; counter++) {
|
||||
if (!mbox->m_in.busy)
|
||||
return 0;
|
||||
udelay(100); yield();
|
||||
udelay(100);
|
||||
cond_resched();
|
||||
}
|
||||
return -1; /* give up after 1 second */
|
||||
}
|
||||
|
@ -3177,7 +3178,10 @@ proc_rdrv(adapter_t *adapter, char *page, int start, int end )
|
|||
|
||||
return len;
|
||||
}
|
||||
|
||||
#else
|
||||
static inline void mega_create_proc_entry(int index, struct proc_dir_entry *parent)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -4342,7 +4346,7 @@ mega_support_cluster(adapter_t *adapter)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
/**
|
||||
* mega_adapinq()
|
||||
* @adapter - pointer to our soft state
|
||||
|
@ -4447,7 +4451,7 @@ mega_internal_dev_inquiry(adapter_t *adapter, u8 ch, u8 tgt,
|
|||
|
||||
return rval;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* mega_internal_command()
|
||||
|
@ -4965,7 +4969,6 @@ megaraid_remove_one(struct pci_dev *pdev)
|
|||
{
|
||||
struct Scsi_Host *host = pci_get_drvdata(pdev);
|
||||
adapter_t *adapter = (adapter_t *)host->hostdata;
|
||||
char buf[12] = { 0 };
|
||||
|
||||
scsi_remove_host(host);
|
||||
|
||||
|
@ -5011,8 +5014,11 @@ megaraid_remove_one(struct pci_dev *pdev)
|
|||
remove_proc_entry("raiddrives-30-39",
|
||||
adapter->controller_proc_dir_entry);
|
||||
#endif
|
||||
sprintf(buf, "hba%d", adapter->host->host_no);
|
||||
remove_proc_entry(buf, mega_proc_dir_entry);
|
||||
{
|
||||
char buf[12] = { 0 };
|
||||
sprintf(buf, "hba%d", adapter->host->host_no);
|
||||
remove_proc_entry(buf, mega_proc_dir_entry);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1002,7 +1002,6 @@ static int megaraid_reset(Scsi_Cmnd *);
|
|||
static int megaraid_abort_and_reset(adapter_t *, Scsi_Cmnd *, int);
|
||||
static int megaraid_biosparam(struct scsi_device *, struct block_device *,
|
||||
sector_t, int []);
|
||||
static int mega_print_inquiry(char *, char *);
|
||||
|
||||
static int mega_build_sglist (adapter_t *adapter, scb_t *scb,
|
||||
u32 *buffer, u32 *length);
|
||||
|
@ -1024,6 +1023,7 @@ static int mega_init_scb (adapter_t *);
|
|||
static int mega_is_bios_enabled (adapter_t *);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static int mega_print_inquiry(char *, char *);
|
||||
static void mega_create_proc_entry(int, struct proc_dir_entry *);
|
||||
static int proc_read_config(char *, char **, off_t, int, int *, void *);
|
||||
static int proc_read_stat(char *, char **, off_t, int, int *, void *);
|
||||
|
@ -1040,10 +1040,10 @@ static int proc_rdrv_20(char *, char **, off_t, int, int *, void *);
|
|||
static int proc_rdrv_30(char *, char **, off_t, int, int *, void *);
|
||||
static int proc_rdrv_40(char *, char **, off_t, int, int *, void *);
|
||||
static int proc_rdrv(adapter_t *, char *, int, int);
|
||||
#endif
|
||||
|
||||
static int mega_adapinq(adapter_t *, dma_addr_t);
|
||||
static int mega_internal_dev_inquiry(adapter_t *, u8, u8, dma_addr_t);
|
||||
#endif
|
||||
|
||||
static int mega_support_ext_cdb(adapter_t *);
|
||||
static mega_passthru* mega_prepare_passthru(adapter_t *, scb_t *,
|
||||
|
|
|
@ -60,7 +60,7 @@ EXPORT_SYMBOL(mraid_mm_unregister_adp);
|
|||
EXPORT_SYMBOL(mraid_mm_adapter_app_handle);
|
||||
|
||||
static int majorno;
|
||||
static uint32_t drvr_ver = 0x02200206;
|
||||
static uint32_t drvr_ver = 0x02200207;
|
||||
|
||||
static int adapters_count_g;
|
||||
static struct list_head adapters_list_g;
|
||||
|
|
|
@ -185,7 +185,7 @@ struct mesh_state {
|
|||
* Driver is too messy, we need a few prototypes...
|
||||
*/
|
||||
static void mesh_done(struct mesh_state *ms, int start_next);
|
||||
static void mesh_interrupt(int irq, void *dev_id);
|
||||
static void mesh_interrupt(struct mesh_state *ms);
|
||||
static void cmd_complete(struct mesh_state *ms);
|
||||
static void set_dma_cmds(struct mesh_state *ms, struct scsi_cmnd *cmd);
|
||||
static void halt_dma(struct mesh_state *ms);
|
||||
|
@ -466,7 +466,7 @@ static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd)
|
|||
dlog(ms, "intr b4 arb, intr/exc/err/fc=%.8x",
|
||||
MKWORD(mr->interrupt, mr->exception,
|
||||
mr->error, mr->fifo_count));
|
||||
mesh_interrupt(0, (void *)ms);
|
||||
mesh_interrupt(ms);
|
||||
if (ms->phase != arbitrating)
|
||||
return;
|
||||
}
|
||||
|
@ -504,7 +504,7 @@ static void mesh_start_cmd(struct mesh_state *ms, struct scsi_cmnd *cmd)
|
|||
dlog(ms, "intr after disresel, intr/exc/err/fc=%.8x",
|
||||
MKWORD(mr->interrupt, mr->exception,
|
||||
mr->error, mr->fifo_count));
|
||||
mesh_interrupt(0, (void *)ms);
|
||||
mesh_interrupt(ms);
|
||||
if (ms->phase != arbitrating)
|
||||
return;
|
||||
dlog(ms, "after intr after disresel, intr/exc/err/fc=%.8x",
|
||||
|
@ -1018,10 +1018,11 @@ static void handle_reset(struct mesh_state *ms)
|
|||
static irqreturn_t do_mesh_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
unsigned long flags;
|
||||
struct Scsi_Host *dev = ((struct mesh_state *)dev_id)->host;
|
||||
struct mesh_state *ms = dev_id;
|
||||
struct Scsi_Host *dev = ms->host;
|
||||
|
||||
spin_lock_irqsave(dev->host_lock, flags);
|
||||
mesh_interrupt(irq, dev_id);
|
||||
mesh_interrupt(ms);
|
||||
spin_unlock_irqrestore(dev->host_lock, flags);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
@ -1661,9 +1662,8 @@ static int mesh_queue(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
|
|||
* handler (do_mesh_interrupt) or by other functions in
|
||||
* exceptional circumstances
|
||||
*/
|
||||
static void mesh_interrupt(int irq, void *dev_id)
|
||||
static void mesh_interrupt(struct mesh_state *ms)
|
||||
{
|
||||
struct mesh_state *ms = (struct mesh_state *) dev_id;
|
||||
volatile struct mesh_regs __iomem *mr = ms->mesh;
|
||||
int intr;
|
||||
|
||||
|
|
|
@ -4293,7 +4293,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
ha->devnum = devnum; /* specifies microcode load address */
|
||||
|
||||
#ifdef QLA_64BIT_PTR
|
||||
if (pci_set_dma_mask(ha->pdev, (dma_addr_t) ~ 0ULL)) {
|
||||
if (pci_set_dma_mask(ha->pdev, DMA_64BIT_MASK)) {
|
||||
if (pci_set_dma_mask(ha->pdev, DMA_32BIT_MASK)) {
|
||||
printk(KERN_WARNING "scsi(%li): Unable to set a "
|
||||
"suitable DMA mask - aborting\n", ha->host_no);
|
||||
|
|
|
@ -130,18 +130,17 @@ qla2x00_initialize_adapter(scsi_qla_host_t *ha)
|
|||
int
|
||||
qla2100_pci_config(scsi_qla_host_t *ha)
|
||||
{
|
||||
uint16_t w, mwi;
|
||||
int ret;
|
||||
uint16_t w;
|
||||
uint32_t d;
|
||||
unsigned long flags;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
pci_set_master(ha->pdev);
|
||||
mwi = 0;
|
||||
if (pci_set_mwi(ha->pdev))
|
||||
mwi = PCI_COMMAND_INVALIDATE;
|
||||
ret = pci_set_mwi(ha->pdev);
|
||||
|
||||
pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
|
||||
w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
|
||||
w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
|
||||
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
|
||||
|
||||
/* Reset expansion ROM address decode enable */
|
||||
|
@ -166,22 +165,22 @@ qla2100_pci_config(scsi_qla_host_t *ha)
|
|||
int
|
||||
qla2300_pci_config(scsi_qla_host_t *ha)
|
||||
{
|
||||
uint16_t w, mwi;
|
||||
int ret;
|
||||
uint16_t w;
|
||||
uint32_t d;
|
||||
unsigned long flags = 0;
|
||||
uint32_t cnt;
|
||||
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
|
||||
|
||||
pci_set_master(ha->pdev);
|
||||
mwi = 0;
|
||||
if (pci_set_mwi(ha->pdev))
|
||||
mwi = PCI_COMMAND_INVALIDATE;
|
||||
ret = pci_set_mwi(ha->pdev);
|
||||
|
||||
pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
|
||||
w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
|
||||
w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
|
||||
|
||||
if (IS_QLA2322(ha) || IS_QLA6322(ha))
|
||||
w &= ~PCI_COMMAND_INTX_DISABLE;
|
||||
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
|
||||
|
||||
/*
|
||||
* If this is a 2300 card and not 2312, reset the
|
||||
|
@ -210,7 +209,7 @@ qla2300_pci_config(scsi_qla_host_t *ha)
|
|||
ha->fb_rev = RD_FB_CMD_REG(ha, reg);
|
||||
|
||||
if (ha->fb_rev == FPM_2300)
|
||||
w &= ~PCI_COMMAND_INVALIDATE;
|
||||
pci_clear_mwi(ha->pdev);
|
||||
|
||||
/* Deselect FPM registers. */
|
||||
WRT_REG_WORD(®->ctrl_status, 0x0);
|
||||
|
@ -227,7 +226,6 @@ qla2300_pci_config(scsi_qla_host_t *ha)
|
|||
|
||||
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||
}
|
||||
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
|
||||
|
||||
pci_write_config_byte(ha->pdev, PCI_LATENCY_TIMER, 0x80);
|
||||
|
||||
|
@ -253,19 +251,18 @@ qla2300_pci_config(scsi_qla_host_t *ha)
|
|||
int
|
||||
qla24xx_pci_config(scsi_qla_host_t *ha)
|
||||
{
|
||||
uint16_t w, mwi;
|
||||
int ret;
|
||||
uint16_t w;
|
||||
uint32_t d;
|
||||
unsigned long flags = 0;
|
||||
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
|
||||
int pcix_cmd_reg, pcie_dctl_reg;
|
||||
|
||||
pci_set_master(ha->pdev);
|
||||
mwi = 0;
|
||||
if (pci_set_mwi(ha->pdev))
|
||||
mwi = PCI_COMMAND_INVALIDATE;
|
||||
ret = pci_set_mwi(ha->pdev);
|
||||
|
||||
pci_read_config_word(ha->pdev, PCI_COMMAND, &w);
|
||||
w |= mwi | (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
|
||||
w |= (PCI_COMMAND_PARITY | PCI_COMMAND_SERR);
|
||||
w &= ~PCI_COMMAND_INTX_DISABLE;
|
||||
pci_write_config_word(ha->pdev, PCI_COMMAND, w);
|
||||
|
||||
|
@ -3931,6 +3928,8 @@ qla2x00_try_to_stop_firmware(scsi_qla_host_t *ha)
|
|||
|
||||
if (!IS_QLA24XX(ha) && !IS_QLA54XX(ha))
|
||||
return;
|
||||
if (!ha->fw_major_version)
|
||||
return;
|
||||
|
||||
ret = qla2x00_stop_firmware(ha);
|
||||
for (retries = 5; ret != QLA_SUCCESS && retries ; retries--) {
|
||||
|
|
|
@ -1726,6 +1726,17 @@ qla2x00_request_irqs(scsi_qla_host_t *ha)
|
|||
qla_printk(KERN_WARNING, ha,
|
||||
"MSI-X: Falling back-to INTa mode -- %d.\n", ret);
|
||||
skip_msix:
|
||||
|
||||
if (!IS_QLA24XX(ha))
|
||||
goto skip_msi;
|
||||
|
||||
ret = pci_enable_msi(ha->pdev);
|
||||
if (!ret) {
|
||||
DEBUG2(qla_printk(KERN_INFO, ha, "MSI: Enabled.\n"));
|
||||
ha->flags.msi_enabled = 1;
|
||||
}
|
||||
skip_msi:
|
||||
|
||||
ret = request_irq(ha->pdev->irq, ha->isp_ops.intr_handler,
|
||||
IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, ha);
|
||||
if (!ret) {
|
||||
|
@ -1746,6 +1757,8 @@ qla2x00_free_irqs(scsi_qla_host_t *ha)
|
|||
|
||||
if (ha->flags.msix_enabled)
|
||||
qla24xx_disable_msix(ha);
|
||||
else if (ha->flags.inta_enabled)
|
||||
else if (ha->flags.inta_enabled) {
|
||||
free_irq(ha->host->irq, ha);
|
||||
pci_disable_msi(ha->pdev);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ module_param(ql2xlogintimeout, int, S_IRUGO|S_IRUSR);
|
|||
MODULE_PARM_DESC(ql2xlogintimeout,
|
||||
"Login timeout value in seconds.");
|
||||
|
||||
int qlport_down_retry = 30;
|
||||
int qlport_down_retry;
|
||||
module_param(qlport_down_retry, int, S_IRUGO|S_IRUSR);
|
||||
MODULE_PARM_DESC(qlport_down_retry,
|
||||
"Maximum number of command retries to a port that returns "
|
||||
|
@ -1577,9 +1577,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
|
|||
goto probe_failed;
|
||||
}
|
||||
|
||||
if (qla2x00_initialize_adapter(ha) &&
|
||||
!(ha->device_flags & DFLG_NO_CABLE)) {
|
||||
|
||||
if (qla2x00_initialize_adapter(ha)) {
|
||||
qla_printk(KERN_WARNING, ha,
|
||||
"Failed to initialize adapter\n");
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
/*
|
||||
* Driver version
|
||||
*/
|
||||
#define QLA2XXX_VERSION "8.01.07-k6"
|
||||
#define QLA2XXX_VERSION "8.01.07-k7"
|
||||
|
||||
#define QLA_DRIVER_MAJOR_VER 8
|
||||
#define QLA_DRIVER_MINOR_VER 1
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "ql4_def.h"
|
||||
#include <scsi/scsi_dbg.h>
|
||||
|
||||
#if 0
|
||||
|
||||
static void qla4xxx_print_srb_info(struct srb * srb)
|
||||
{
|
||||
printk("%s: srb = 0x%p, flags=0x%02x\n", __func__, srb, srb->flags);
|
||||
|
@ -195,3 +197,5 @@ void qla4xxx_dump_buffer(void *b, uint32_t size)
|
|||
if (cnt % 16)
|
||||
printk(KERN_DEBUG "\n");
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
|
|
@ -43,8 +43,6 @@ int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
|
|||
uint16_t *tcp_source_port_num,
|
||||
uint16_t *connection_id);
|
||||
|
||||
struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host * ha,
|
||||
uint32_t fw_ddb_index);
|
||||
int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
|
||||
dma_addr_t fw_ddb_entry_dma);
|
||||
|
||||
|
@ -55,18 +53,11 @@ void qla4xxx_get_crash_record(struct scsi_qla_host * ha);
|
|||
struct ddb_entry *qla4xxx_alloc_sess(struct scsi_qla_host *ha);
|
||||
int qla4xxx_add_sess(struct ddb_entry *);
|
||||
void qla4xxx_destroy_sess(struct ddb_entry *ddb_entry);
|
||||
int qla4xxx_conn_close_sess_logout(struct scsi_qla_host * ha,
|
||||
uint16_t fw_ddb_index,
|
||||
uint16_t connection_id,
|
||||
uint16_t option);
|
||||
int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
|
||||
uint16_t fw_ddb_index);
|
||||
int qla4xxx_is_nvram_configuration_valid(struct scsi_qla_host * ha);
|
||||
int qla4xxx_get_fw_version(struct scsi_qla_host * ha);
|
||||
void qla4xxx_interrupt_service_routine(struct scsi_qla_host * ha,
|
||||
uint32_t intr_status);
|
||||
int qla4xxx_init_rings(struct scsi_qla_host * ha);
|
||||
void qla4xxx_dump_buffer(void *b, uint32_t size);
|
||||
struct srb * qla4xxx_del_from_active_array(struct scsi_qla_host *ha, uint32_t index);
|
||||
void qla4xxx_srb_compl(struct scsi_qla_host *ha, struct srb *srb);
|
||||
int qla4xxx_reinitialize_ddb_list(struct scsi_qla_host * ha);
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
|
||||
#include "ql4_def.h"
|
||||
|
||||
/*
|
||||
* QLogic ISP4xxx Hardware Support Function Prototypes.
|
||||
*/
|
||||
static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
|
||||
uint32_t fw_ddb_index);
|
||||
|
||||
static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
|
||||
{
|
||||
|
@ -48,7 +47,8 @@ static void ql4xxx_set_mac_number(struct scsi_qla_host *ha)
|
|||
* This routine deallocates and unlinks the specified ddb_entry from the
|
||||
* adapter's
|
||||
**/
|
||||
void qla4xxx_free_ddb(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry)
|
||||
static void qla4xxx_free_ddb(struct scsi_qla_host *ha,
|
||||
struct ddb_entry *ddb_entry)
|
||||
{
|
||||
/* Remove device entry from list */
|
||||
list_del_init(&ddb_entry->list);
|
||||
|
@ -370,9 +370,9 @@ static struct ddb_entry* qla4xxx_get_ddb_entry(struct scsi_qla_host *ha,
|
|||
* must be initialized prior to calling this routine
|
||||
*
|
||||
**/
|
||||
int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
|
||||
struct ddb_entry *ddb_entry,
|
||||
uint32_t fw_ddb_index)
|
||||
static int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
|
||||
struct ddb_entry *ddb_entry,
|
||||
uint32_t fw_ddb_index)
|
||||
{
|
||||
struct dev_db_entry *fw_ddb_entry = NULL;
|
||||
dma_addr_t fw_ddb_entry_dma;
|
||||
|
@ -450,8 +450,8 @@ int qla4xxx_update_ddb_entry(struct scsi_qla_host *ha,
|
|||
* This routine allocates a ddb_entry, ititializes some values, and
|
||||
* inserts it into the ddb list.
|
||||
**/
|
||||
struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
|
||||
uint32_t fw_ddb_index)
|
||||
static struct ddb_entry * qla4xxx_alloc_ddb(struct scsi_qla_host *ha,
|
||||
uint32_t fw_ddb_index)
|
||||
{
|
||||
struct ddb_entry *ddb_entry;
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
* - advances the request_in pointer
|
||||
* - checks for queue full
|
||||
**/
|
||||
int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
|
||||
struct queue_entry **queue_entry)
|
||||
static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
|
||||
struct queue_entry **queue_entry)
|
||||
{
|
||||
uint16_t request_in;
|
||||
uint8_t status = QLA_SUCCESS;
|
||||
|
@ -62,8 +62,8 @@ int qla4xxx_get_req_pkt(struct scsi_qla_host *ha,
|
|||
*
|
||||
* This routine issues a marker IOCB.
|
||||
**/
|
||||
int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
|
||||
struct ddb_entry *ddb_entry, int lun)
|
||||
static int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
|
||||
struct ddb_entry *ddb_entry, int lun)
|
||||
{
|
||||
struct marker_entry *marker_entry;
|
||||
unsigned long flags = 0;
|
||||
|
@ -96,7 +96,7 @@ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha,
|
|||
return status;
|
||||
}
|
||||
|
||||
struct continuation_t1_entry* qla4xxx_alloc_cont_entry(
|
||||
static struct continuation_t1_entry* qla4xxx_alloc_cont_entry(
|
||||
struct scsi_qla_host *ha)
|
||||
{
|
||||
struct continuation_t1_entry *cont_entry;
|
||||
|
@ -120,7 +120,7 @@ struct continuation_t1_entry* qla4xxx_alloc_cont_entry(
|
|||
return cont_entry;
|
||||
}
|
||||
|
||||
uint16_t qla4xxx_calc_request_entries(uint16_t dsds)
|
||||
static uint16_t qla4xxx_calc_request_entries(uint16_t dsds)
|
||||
{
|
||||
uint16_t iocbs;
|
||||
|
||||
|
@ -133,9 +133,9 @@ uint16_t qla4xxx_calc_request_entries(uint16_t dsds)
|
|||
return iocbs;
|
||||
}
|
||||
|
||||
void qla4xxx_build_scsi_iocbs(struct srb *srb,
|
||||
struct command_t3_entry *cmd_entry,
|
||||
uint16_t tot_dsds)
|
||||
static void qla4xxx_build_scsi_iocbs(struct srb *srb,
|
||||
struct command_t3_entry *cmd_entry,
|
||||
uint16_t tot_dsds)
|
||||
{
|
||||
struct scsi_qla_host *ha;
|
||||
uint16_t avail_dsds;
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
* If outCount is 0, this routine completes successfully WITHOUT waiting
|
||||
* for the mailbox command to complete.
|
||||
**/
|
||||
int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
||||
uint8_t outCount, uint32_t *mbx_cmd,
|
||||
uint32_t *mbx_sts)
|
||||
static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
||||
uint8_t outCount, uint32_t *mbx_cmd,
|
||||
uint32_t *mbx_sts)
|
||||
{
|
||||
int status = QLA_ERROR;
|
||||
uint8_t i;
|
||||
|
@ -170,6 +170,8 @@ int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
|
|||
}
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
/**
|
||||
* qla4xxx_issue_iocb - issue mailbox iocb command
|
||||
* @ha: adapter state pointer.
|
||||
|
@ -243,6 +245,8 @@ int qla4xxx_clear_database_entry(struct scsi_qla_host * ha,
|
|||
return QLA_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* 0 */
|
||||
|
||||
/**
|
||||
* qla4xxx_initialize_fw_cb - initializes firmware control block.
|
||||
* @ha: Pointer to host adapter structure.
|
||||
|
@ -570,6 +574,7 @@ int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
|
|||
return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
|
||||
uint16_t fw_ddb_index)
|
||||
{
|
||||
|
@ -594,6 +599,7 @@ int qla4xxx_conn_open_session_login(struct scsi_qla_host * ha,
|
|||
|
||||
return status;
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/**
|
||||
* qla4xxx_get_crash_record - retrieves crash record.
|
||||
|
@ -649,6 +655,7 @@ void qla4xxx_get_crash_record(struct scsi_qla_host * ha)
|
|||
crash_record, crash_record_dma);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* qla4xxx_get_conn_event_log - retrieves connection event log
|
||||
* @ha: Pointer to host adapter structure.
|
||||
|
@ -738,6 +745,7 @@ void qla4xxx_get_conn_event_log(struct scsi_qla_host * ha)
|
|||
dma_free_coherent(&ha->pdev->dev, event_log_size, event_log,
|
||||
event_log_dma);
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
/**
|
||||
* qla4xxx_reset_lun - issues LUN Reset
|
||||
|
@ -834,7 +842,8 @@ int qla4xxx_get_fw_version(struct scsi_qla_host * ha)
|
|||
return QLA_SUCCESS;
|
||||
}
|
||||
|
||||
int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, dma_addr_t dma_addr)
|
||||
static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
|
||||
dma_addr_t dma_addr)
|
||||
{
|
||||
uint32_t mbox_cmd[MBOX_REG_COUNT];
|
||||
uint32_t mbox_sts[MBOX_REG_COUNT];
|
||||
|
@ -855,7 +864,7 @@ int qla4xxx_get_default_ddb(struct scsi_qla_host *ha, dma_addr_t dma_addr)
|
|||
return QLA_SUCCESS;
|
||||
}
|
||||
|
||||
int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
|
||||
static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
|
||||
{
|
||||
uint32_t mbox_cmd[MBOX_REG_COUNT];
|
||||
uint32_t mbox_sts[MBOX_REG_COUNT];
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
/*
|
||||
* Driver version
|
||||
*/
|
||||
char qla4xxx_version_str[40];
|
||||
static char qla4xxx_version_str[40];
|
||||
|
||||
/*
|
||||
* SRB allocation cache
|
||||
|
@ -45,8 +45,7 @@ int ql4_mod_unload = 0;
|
|||
/*
|
||||
* SCSI host template entry points
|
||||
*/
|
||||
|
||||
void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
|
||||
static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha);
|
||||
|
||||
/*
|
||||
* iSCSI template entry points
|
||||
|
@ -1352,7 +1351,7 @@ static void __devexit qla4xxx_remove_adapter(struct pci_dev *pdev)
|
|||
* At exit, the @ha's flags.enable_64bit_addressing set to indicated
|
||||
* supported addressing method.
|
||||
*/
|
||||
void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
|
||||
static void qla4xxx_config_dma_addressing(struct scsi_qla_host *ha)
|
||||
{
|
||||
int retval;
|
||||
|
||||
|
@ -1627,7 +1626,7 @@ static struct pci_device_id qla4xxx_pci_tbl[] = {
|
|||
};
|
||||
MODULE_DEVICE_TABLE(pci, qla4xxx_pci_tbl);
|
||||
|
||||
struct pci_driver qla4xxx_pci_driver = {
|
||||
static struct pci_driver qla4xxx_pci_driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.id_table = qla4xxx_pci_tbl,
|
||||
.probe = qla4xxx_probe_adapter,
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "scsi_logging.h"
|
||||
|
||||
#define SENSE_TIMEOUT (10*HZ)
|
||||
#define START_UNIT_TIMEOUT (30*HZ)
|
||||
|
||||
/*
|
||||
* These should *probably* be handled by the host itself.
|
||||
|
@ -936,7 +935,7 @@ static int scsi_eh_try_stu(struct scsi_cmnd *scmd)
|
|||
|
||||
for (i = 0; rtn == NEEDS_RETRY && i < 2; i++)
|
||||
rtn = scsi_send_eh_cmnd(scmd, stu_command, 6,
|
||||
START_UNIT_TIMEOUT, 0);
|
||||
scmd->device->timeout, 0);
|
||||
|
||||
if (rtn == SUCCESS)
|
||||
return 0;
|
||||
|
|
|
@ -1718,31 +1718,12 @@ fc_starget_delete(struct work_struct *work)
|
|||
struct fc_rport *rport =
|
||||
container_of(work, struct fc_rport, stgt_delete_work);
|
||||
struct Scsi_Host *shost = rport_to_shost(rport);
|
||||
unsigned long flags;
|
||||
struct fc_internal *i = to_fc_internal(shost->transportt);
|
||||
|
||||
/*
|
||||
* Involve the LLDD if possible. All io on the rport is to
|
||||
* be terminated, either as part of the dev_loss_tmo callback
|
||||
* processing, or via the terminate_rport_io function.
|
||||
*/
|
||||
if (i->f->dev_loss_tmo_callbk)
|
||||
i->f->dev_loss_tmo_callbk(rport);
|
||||
else if (i->f->terminate_rport_io)
|
||||
/* Involve the LLDD if possible to terminate all io on the rport. */
|
||||
if (i->f->terminate_rport_io)
|
||||
i->f->terminate_rport_io(rport);
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
if (!cancel_delayed_work(&rport->fail_io_work))
|
||||
fc_flush_devloss(shost);
|
||||
if (!cancel_delayed_work(&rport->dev_loss_work))
|
||||
fc_flush_devloss(shost);
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
|
||||
}
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
||||
scsi_remove_target(&rport->dev);
|
||||
}
|
||||
|
||||
|
@ -1760,6 +1741,7 @@ fc_rport_final_delete(struct work_struct *work)
|
|||
struct device *dev = &rport->dev;
|
||||
struct Scsi_Host *shost = rport_to_shost(rport);
|
||||
struct fc_internal *i = to_fc_internal(shost->transportt);
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* if a scan is pending, flush the SCSI Host work_q so that
|
||||
|
@ -1768,13 +1750,37 @@ fc_rport_final_delete(struct work_struct *work)
|
|||
if (rport->flags & FC_RPORT_SCAN_PENDING)
|
||||
scsi_flush_work(shost);
|
||||
|
||||
/* involve the LLDD to terminate all pending i/o */
|
||||
if (i->f->terminate_rport_io)
|
||||
i->f->terminate_rport_io(rport);
|
||||
|
||||
/*
|
||||
* Cancel any outstanding timers. These should really exist
|
||||
* only when rmmod'ing the LLDD and we're asking for
|
||||
* immediate termination of the rports
|
||||
*/
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
if (rport->flags & FC_RPORT_DEVLOSS_PENDING) {
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
if (!cancel_delayed_work(&rport->fail_io_work))
|
||||
fc_flush_devloss(shost);
|
||||
if (!cancel_delayed_work(&rport->dev_loss_work))
|
||||
fc_flush_devloss(shost);
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
|
||||
}
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
||||
/* Delete SCSI target and sdevs */
|
||||
if (rport->scsi_target_id != -1)
|
||||
fc_starget_delete(&rport->stgt_delete_work);
|
||||
else if (i->f->dev_loss_tmo_callbk)
|
||||
|
||||
/*
|
||||
* Notify the driver that the rport is now dead. The LLDD will
|
||||
* also guarantee that any communication to the rport is terminated
|
||||
*/
|
||||
if (i->f->dev_loss_tmo_callbk)
|
||||
i->f->dev_loss_tmo_callbk(rport);
|
||||
else if (i->f->terminate_rport_io)
|
||||
i->f->terminate_rport_io(rport);
|
||||
|
||||
transport_remove_device(dev);
|
||||
device_del(dev);
|
||||
|
@ -1963,8 +1969,6 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
|
|||
}
|
||||
|
||||
if (match) {
|
||||
struct delayed_work *work =
|
||||
&rport->dev_loss_work;
|
||||
|
||||
memcpy(&rport->node_name, &ids->node_name,
|
||||
sizeof(rport->node_name));
|
||||
|
@ -1982,46 +1986,61 @@ fc_remote_port_add(struct Scsi_Host *shost, int channel,
|
|||
fci->f->dd_fcrport_size);
|
||||
|
||||
/*
|
||||
* If we were blocked, we were a target.
|
||||
* If no longer a target, we leave the timer
|
||||
* running in case the port changes roles
|
||||
* prior to the timer expiring. If the timer
|
||||
* fires, the target will be torn down.
|
||||
* If we were not a target, cancel the
|
||||
* io terminate and rport timers, and
|
||||
* we're done.
|
||||
*
|
||||
* If we were a target, but our new role
|
||||
* doesn't indicate a target, leave the
|
||||
* timers running expecting the role to
|
||||
* change as the target fully logs in. If
|
||||
* it doesn't, the target will be torn down.
|
||||
*
|
||||
* If we were a target, and our role shows
|
||||
* we're still a target, cancel the timers
|
||||
* and kick off a scan.
|
||||
*/
|
||||
if (!(ids->roles & FC_RPORT_ROLE_FCP_TARGET))
|
||||
|
||||
/* was a target, not in roles */
|
||||
if ((rport->scsi_target_id != -1) &&
|
||||
(!(ids->roles & FC_RPORT_ROLE_FCP_TARGET)))
|
||||
return rport;
|
||||
|
||||
/* restart the target */
|
||||
|
||||
/*
|
||||
* Stop the target timers first. Take no action
|
||||
* on the del_timer failure as the state
|
||||
* machine state change will validate the
|
||||
* transaction.
|
||||
* Stop the fail io and dev_loss timers.
|
||||
* If they flush, the port_state will
|
||||
* be checked and will NOOP the function.
|
||||
*/
|
||||
if (!cancel_delayed_work(&rport->fail_io_work))
|
||||
fc_flush_devloss(shost);
|
||||
if (!cancel_delayed_work(work))
|
||||
if (!cancel_delayed_work(&rport->dev_loss_work))
|
||||
fc_flush_devloss(shost);
|
||||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
|
||||
rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
|
||||
|
||||
/* initiate a scan of the target */
|
||||
rport->flags |= FC_RPORT_SCAN_PENDING;
|
||||
scsi_queue_work(shost, &rport->scan_work);
|
||||
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
|
||||
scsi_target_unblock(&rport->dev);
|
||||
/* if target, initiate a scan */
|
||||
if (rport->scsi_target_id != -1) {
|
||||
rport->flags |= FC_RPORT_SCAN_PENDING;
|
||||
scsi_queue_work(shost,
|
||||
&rport->scan_work);
|
||||
spin_unlock_irqrestore(shost->host_lock,
|
||||
flags);
|
||||
scsi_target_unblock(&rport->dev);
|
||||
} else
|
||||
spin_unlock_irqrestore(shost->host_lock,
|
||||
flags);
|
||||
|
||||
return rport;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Search the bindings array */
|
||||
/*
|
||||
* Search the bindings array
|
||||
* Note: if never a FCP target, you won't be on this list
|
||||
*/
|
||||
if (fc_host->tgtid_bind_type != FC_TGTID_BIND_NONE) {
|
||||
|
||||
/* search for a matching consistent binding */
|
||||
|
@ -2158,15 +2177,24 @@ fc_remote_port_delete(struct fc_rport *rport)
|
|||
|
||||
spin_lock_irqsave(shost->host_lock, flags);
|
||||
|
||||
/* If no scsi target id mapping, delete it */
|
||||
if (rport->scsi_target_id == -1) {
|
||||
list_del(&rport->peers);
|
||||
rport->port_state = FC_PORTSTATE_DELETED;
|
||||
fc_queue_work(shost, &rport->rport_delete_work);
|
||||
if (rport->port_state != FC_PORTSTATE_ONLINE) {
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* In the past, we if this was not an FCP-Target, we would
|
||||
* unconditionally just jump to deleting the rport.
|
||||
* However, rports can be used as node containers by the LLDD,
|
||||
* and its not appropriate to just terminate the rport at the
|
||||
* first sign of a loss in connectivity. The LLDD may want to
|
||||
* send ELS traffic to re-validate the login. If the rport is
|
||||
* immediately deleted, it makes it inappropriate for a node
|
||||
* container.
|
||||
* So... we now unconditionally wait dev_loss_tmo before
|
||||
* destroying an rport.
|
||||
*/
|
||||
|
||||
rport->port_state = FC_PORTSTATE_BLOCKED;
|
||||
|
||||
rport->flags |= FC_RPORT_DEVLOSS_PENDING;
|
||||
|
@ -2263,11 +2291,11 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles)
|
|||
EXPORT_SYMBOL(fc_remote_port_rolechg);
|
||||
|
||||
/**
|
||||
* fc_timeout_deleted_rport - Timeout handler for a deleted remote port that
|
||||
* was a SCSI target (thus was blocked), and failed
|
||||
* to return in the alloted time.
|
||||
* fc_timeout_deleted_rport - Timeout handler for a deleted remote port,
|
||||
* which we blocked, and has now failed to return
|
||||
* in the allotted time.
|
||||
*
|
||||
* @work: rport target that failed to reappear in the alloted time.
|
||||
* @work: rport target that failed to reappear in the allotted time.
|
||||
**/
|
||||
static void
|
||||
fc_timeout_deleted_rport(struct work_struct *work)
|
||||
|
@ -2283,10 +2311,12 @@ fc_timeout_deleted_rport(struct work_struct *work)
|
|||
rport->flags &= ~FC_RPORT_DEVLOSS_PENDING;
|
||||
|
||||
/*
|
||||
* If the port is ONLINE, then it came back. Validate it's still an
|
||||
* FCP target. If not, tear down the scsi_target on it.
|
||||
* If the port is ONLINE, then it came back. If it was a SCSI
|
||||
* target, validate it still is. If not, tear down the
|
||||
* scsi_target on it.
|
||||
*/
|
||||
if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
|
||||
(rport->scsi_target_id != -1) &&
|
||||
!(rport->roles & FC_RPORT_ROLE_FCP_TARGET)) {
|
||||
dev_printk(KERN_ERR, &rport->dev,
|
||||
"blocked FC remote port time out: no longer"
|
||||
|
@ -2297,18 +2327,24 @@ fc_timeout_deleted_rport(struct work_struct *work)
|
|||
return;
|
||||
}
|
||||
|
||||
/* NOOP state - we're flushing workq's */
|
||||
if (rport->port_state != FC_PORTSTATE_BLOCKED) {
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
dev_printk(KERN_ERR, &rport->dev,
|
||||
"blocked FC remote port time out: leaving target alone\n");
|
||||
"blocked FC remote port time out: leaving"
|
||||
" rport%s alone\n",
|
||||
(rport->scsi_target_id != -1) ? " and starget" : "");
|
||||
return;
|
||||
}
|
||||
|
||||
if (fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) {
|
||||
if ((fc_host->tgtid_bind_type == FC_TGTID_BIND_NONE) ||
|
||||
(rport->scsi_target_id == -1)) {
|
||||
list_del(&rport->peers);
|
||||
rport->port_state = FC_PORTSTATE_DELETED;
|
||||
dev_printk(KERN_ERR, &rport->dev,
|
||||
"blocked FC remote port time out: removing target\n");
|
||||
"blocked FC remote port time out: removing"
|
||||
" rport%s\n",
|
||||
(rport->scsi_target_id != -1) ? " and starget" : "");
|
||||
fc_queue_work(shost, &rport->rport_delete_work);
|
||||
spin_unlock_irqrestore(shost->host_lock, flags);
|
||||
return;
|
||||
|
|
|
@ -351,6 +351,27 @@ static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
|
|||
* (DCBs, SRBs, Queueing)
|
||||
*
|
||||
**********************************************************************/
|
||||
static void inline dc390_start_segment(struct dc390_srb* pSRB)
|
||||
{
|
||||
struct scatterlist *psgl = pSRB->pSegmentList;
|
||||
|
||||
/* start new sg segment */
|
||||
pSRB->SGBusAddr = sg_dma_address(psgl);
|
||||
pSRB->SGToBeXferLen = sg_dma_len(psgl);
|
||||
}
|
||||
|
||||
static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
|
||||
{
|
||||
unsigned long xfer = pSRB->SGToBeXferLen - residue;
|
||||
|
||||
/* xfer more bytes transferred */
|
||||
pSRB->SGBusAddr += xfer;
|
||||
pSRB->TotalXferredLen += xfer;
|
||||
pSRB->SGToBeXferLen = residue;
|
||||
|
||||
return xfer;
|
||||
}
|
||||
|
||||
static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
|
||||
{
|
||||
struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
|
||||
|
@ -625,70 +646,6 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr
|
|||
return 0;
|
||||
}
|
||||
|
||||
//#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/
|
||||
#define DMA_INT 0
|
||||
|
||||
#if DMA_INT
|
||||
/* This is similar to AM53C974.c ... */
|
||||
static u8
|
||||
dc390_dma_intr (struct dc390_acb* pACB)
|
||||
{
|
||||
struct dc390_srb* pSRB;
|
||||
u8 dstate;
|
||||
DEBUG0(u16 pstate; struct pci_dev *pdev = pACB->pdev);
|
||||
|
||||
DEBUG0(pci_read_config_word(pdev, PCI_STATUS, &pstate));
|
||||
DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\
|
||||
{ printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \
|
||||
pci_write_config_word(pdev, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));});
|
||||
|
||||
dstate = DC390_read8 (DMA_Status);
|
||||
|
||||
if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate;
|
||||
else pSRB = pACB->pActiveDCB->pActiveSRB;
|
||||
|
||||
if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT))
|
||||
{
|
||||
printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate);
|
||||
return dstate;
|
||||
}
|
||||
if (dstate & DMA_XFER_DONE)
|
||||
{
|
||||
u32 residual, xferCnt; int ctr = 6000000;
|
||||
if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION))
|
||||
{
|
||||
do
|
||||
{
|
||||
DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n"));
|
||||
dstate = DC390_read8 (DMA_Status);
|
||||
residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 |
|
||||
DC390_read8 (CtcReg_High) << 16;
|
||||
residual += DC390_read8 (Current_Fifo) & 0x1f;
|
||||
} while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr);
|
||||
if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr));
|
||||
/* residual = ... */
|
||||
}
|
||||
else
|
||||
residual = 0;
|
||||
|
||||
/* ??? */
|
||||
|
||||
xferCnt = pSRB->SGToBeXferLen - residual;
|
||||
pSRB->SGBusAddr += xferCnt;
|
||||
pSRB->TotalXferredLen += xferCnt;
|
||||
pSRB->SGToBeXferLen = residual;
|
||||
# ifdef DC390_DEBUG0
|
||||
printk (KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n",
|
||||
(unsigned int)residual, (unsigned int)xferCnt);
|
||||
# endif
|
||||
|
||||
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
|
||||
}
|
||||
dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24;
|
||||
return dstate;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static void __inline__
|
||||
dc390_InvalidCmd(struct dc390_acb* pACB)
|
||||
|
@ -708,9 +665,6 @@ DC390_Interrupt(void *dev_id)
|
|||
u8 phase;
|
||||
void (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *);
|
||||
u8 istate, istatus;
|
||||
#if DMA_INT
|
||||
u8 dstatus;
|
||||
#endif
|
||||
|
||||
sstatus = DC390_read8 (Scsi_Status);
|
||||
if( !(sstatus & INTERRUPT) )
|
||||
|
@ -718,22 +672,9 @@ DC390_Interrupt(void *dev_id)
|
|||
|
||||
DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
|
||||
|
||||
#if DMA_INT
|
||||
spin_lock_irq(pACB->pScsiHost->host_lock);
|
||||
dstatus = dc390_dma_intr (pACB);
|
||||
spin_unlock_irq(pACB->pScsiHost->host_lock);
|
||||
|
||||
DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus));
|
||||
if (! (dstatus & SCSI_INTERRUPT))
|
||||
{
|
||||
DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n"));
|
||||
return IRQ_NONE;
|
||||
}
|
||||
#else
|
||||
//DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
|
||||
//dstatus = DC390_read8 (DMA_Status);
|
||||
//DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
|
||||
#endif
|
||||
|
||||
spin_lock_irq(pACB->pScsiHost->host_lock);
|
||||
|
||||
|
@ -821,11 +762,10 @@ static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
|
|||
}
|
||||
|
||||
static void
|
||||
dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
||||
dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
||||
{
|
||||
u8 sstatus;
|
||||
struct scatterlist *psgl;
|
||||
u32 ResidCnt, xferCnt;
|
||||
u32 ResidCnt;
|
||||
u8 dstate = 0;
|
||||
|
||||
sstatus = *psstatus;
|
||||
|
@ -856,42 +796,35 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
|||
if( pSRB->SGIndex < pSRB->SGcount )
|
||||
{
|
||||
pSRB->pSegmentList++;
|
||||
psgl = pSRB->pSegmentList;
|
||||
|
||||
pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
|
||||
pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
|
||||
dc390_start_segment(pSRB);
|
||||
}
|
||||
else
|
||||
pSRB->SGToBeXferLen = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResidCnt = (u32) DC390_read8 (Current_Fifo) & 0x1f;
|
||||
ResidCnt |= (u32) DC390_read8 (CtcReg_High) << 16;
|
||||
ResidCnt |= (u32) DC390_read8 (CtcReg_Mid) << 8;
|
||||
ResidCnt += (u32) DC390_read8 (CtcReg_Low);
|
||||
ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
|
||||
(((u32) DC390_read8 (CtcReg_High) << 16) |
|
||||
((u32) DC390_read8 (CtcReg_Mid) << 8) |
|
||||
(u32) DC390_read8 (CtcReg_Low));
|
||||
|
||||
xferCnt = pSRB->SGToBeXferLen - ResidCnt;
|
||||
pSRB->SGBusAddr += xferCnt;
|
||||
pSRB->TotalXferredLen += xferCnt;
|
||||
pSRB->SGToBeXferLen = ResidCnt;
|
||||
dc390_advance_segment(pSRB, ResidCnt);
|
||||
}
|
||||
}
|
||||
if ((*psstatus & 7) != SCSI_DATA_OUT)
|
||||
{
|
||||
DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
|
||||
DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD);
|
||||
DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
||||
dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
||||
{
|
||||
u8 sstatus, residual, bval;
|
||||
struct scatterlist *psgl;
|
||||
u32 ResidCnt, i;
|
||||
u32 ResidCnt, i;
|
||||
unsigned long xferCnt;
|
||||
u8 *ptr;
|
||||
|
||||
sstatus = *psstatus;
|
||||
|
||||
|
@ -922,19 +855,17 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
|||
DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \
|
||||
+ ((unsigned long) DC390_read8 (CtcReg_Mid) << 8) \
|
||||
+ ((unsigned long) DC390_read8 (CtcReg_Low)));
|
||||
DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen));
|
||||
DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen));
|
||||
|
||||
DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
|
||||
DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
|
||||
|
||||
pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
|
||||
pSRB->SGIndex++;
|
||||
if( pSRB->SGIndex < pSRB->SGcount )
|
||||
{
|
||||
pSRB->pSegmentList++;
|
||||
psgl = pSRB->pSegmentList;
|
||||
|
||||
pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
|
||||
pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
|
||||
dc390_start_segment(pSRB);
|
||||
}
|
||||
else
|
||||
pSRB->SGToBeXferLen = 0;
|
||||
|
@ -973,47 +904,45 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
|||
}
|
||||
/* It seems a DMA Blast abort isn't that bad ... */
|
||||
if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
|
||||
//DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
|
||||
dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;
|
||||
//DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
|
||||
dc390_laststatus &= ~0xff000000;
|
||||
dc390_laststatus |= bval << 24;
|
||||
|
||||
DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
|
||||
ResidCnt = (u32) DC390_read8 (CtcReg_High);
|
||||
ResidCnt <<= 8;
|
||||
ResidCnt |= (u32) DC390_read8 (CtcReg_Mid);
|
||||
ResidCnt <<= 8;
|
||||
ResidCnt |= (u32) DC390_read8 (CtcReg_Low);
|
||||
ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
|
||||
((u32) DC390_read8 (CtcReg_Mid) << 8)) |
|
||||
(u32) DC390_read8 (CtcReg_Low);
|
||||
|
||||
xferCnt = pSRB->SGToBeXferLen - ResidCnt;
|
||||
pSRB->SGBusAddr += xferCnt;
|
||||
pSRB->TotalXferredLen += xferCnt;
|
||||
pSRB->SGToBeXferLen = ResidCnt;
|
||||
xferCnt = dc390_advance_segment(pSRB, ResidCnt);
|
||||
|
||||
if (residual) {
|
||||
size_t count = 1;
|
||||
size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
|
||||
unsigned long flags;
|
||||
u8 *ptr;
|
||||
|
||||
if( residual )
|
||||
{
|
||||
static int feedback_requested;
|
||||
bval = DC390_read8 (ScsiFifo); /* get one residual byte */
|
||||
|
||||
if (!feedback_requested) {
|
||||
feedback_requested = 1;
|
||||
printk(KERN_WARNING "%s: Please, contact <linux-scsi@vger.kernel.org> "
|
||||
"to help improve support for your system.\n", __FILE__);
|
||||
local_irq_save(flags);
|
||||
ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
|
||||
if (likely(ptr)) {
|
||||
*(ptr + offset) = bval;
|
||||
scsi_kunmap_atomic_sg(ptr);
|
||||
}
|
||||
local_irq_restore(flags);
|
||||
WARN_ON(!ptr);
|
||||
|
||||
ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr );
|
||||
*ptr = bval;
|
||||
pSRB->SGBusAddr++; xferCnt++;
|
||||
pSRB->TotalXferredLen++;
|
||||
pSRB->SGToBeXferLen--;
|
||||
/* 1 more byte read */
|
||||
xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
|
||||
}
|
||||
DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\
|
||||
DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
|
||||
pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
|
||||
|
||||
}
|
||||
}
|
||||
if ((*psstatus & 7) != SCSI_DATA_IN)
|
||||
{
|
||||
DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
|
||||
DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */
|
||||
DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1216,7 +1145,7 @@ dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
|
|||
|
||||
|
||||
/* handle RESTORE_PTR */
|
||||
/* I presume, this command is already mapped, so, have to remap. */
|
||||
/* This doesn't look very healthy... to-be-fixed */
|
||||
static void
|
||||
dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
|
||||
{
|
||||
|
@ -1225,6 +1154,7 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
|
|||
pSRB->TotalXferredLen = 0;
|
||||
pSRB->SGIndex = 0;
|
||||
if (pcmd->use_sg) {
|
||||
size_t saved;
|
||||
pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
|
||||
psgl = pSRB->pSegmentList;
|
||||
//dc390_pci_sync(pSRB);
|
||||
|
@ -1236,15 +1166,16 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
|
|||
if( pSRB->SGIndex < pSRB->SGcount )
|
||||
{
|
||||
pSRB->pSegmentList++;
|
||||
psgl = pSRB->pSegmentList;
|
||||
pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
|
||||
pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
|
||||
|
||||
dc390_start_segment(pSRB);
|
||||
}
|
||||
else
|
||||
pSRB->SGToBeXferLen = 0;
|
||||
}
|
||||
pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
|
||||
pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen);
|
||||
|
||||
saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
|
||||
pSRB->SGToBeXferLen -= saved;
|
||||
pSRB->SGBusAddr += saved;
|
||||
printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
|
||||
pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
|
||||
|
||||
|
@ -1365,7 +1296,6 @@ dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
|||
static void
|
||||
dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
|
||||
{
|
||||
struct scatterlist *psgl;
|
||||
unsigned long lval;
|
||||
struct dc390_dcb* pDCB = pACB->pActiveDCB;
|
||||
|
||||
|
@ -1391,12 +1321,11 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
|
|||
|
||||
if( pSRB->SGIndex < pSRB->SGcount )
|
||||
{
|
||||
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */);
|
||||
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
|
||||
if( !pSRB->SGToBeXferLen )
|
||||
{
|
||||
psgl = pSRB->pSegmentList;
|
||||
pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl)));
|
||||
pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl));
|
||||
dc390_start_segment(pSRB);
|
||||
|
||||
DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
|
||||
}
|
||||
lval = pSRB->SGToBeXferLen;
|
||||
|
@ -1410,12 +1339,12 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
|
|||
DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
|
||||
DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
|
||||
|
||||
//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */
|
||||
//DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
|
||||
pSRB->SRBState = SRB_DATA_XFER;
|
||||
|
||||
DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
|
||||
|
||||
DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
|
||||
DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
|
||||
//DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
|
||||
//DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
|
||||
//DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
|
||||
|
@ -1436,8 +1365,8 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
|
|||
pSRB->SRBState |= SRB_XFERPAD;
|
||||
DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
|
||||
/*
|
||||
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT;
|
||||
DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT);
|
||||
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
|
||||
DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,14 +19,6 @@
|
|||
|
||||
#define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */
|
||||
|
||||
#define pci_dma_lo32(a) (a & 0xffffffff)
|
||||
|
||||
typedef u8 UCHAR; /* 8 bits */
|
||||
typedef u16 USHORT; /* 16 bits */
|
||||
typedef u32 UINT; /* 32 bits */
|
||||
typedef unsigned long ULONG; /* 32/64 bits */
|
||||
|
||||
|
||||
/*
|
||||
;-----------------------------------------------------------------------
|
||||
; SCSI Request Block
|
||||
|
@ -43,7 +35,9 @@ struct scatterlist *pSegmentList;
|
|||
|
||||
struct scatterlist Segmentx; /* make a one entry of S/G list table */
|
||||
|
||||
unsigned long SGBusAddr; /*;a segment starting address as seen by AM53C974A*/
|
||||
unsigned long SGBusAddr; /*;a segment starting address as seen by AM53C974A
|
||||
in CPU endianness. We're only getting 32-bit bus
|
||||
addresses by default */
|
||||
unsigned long SGToBeXferLen; /*; to be xfer length */
|
||||
unsigned long TotalXferredLen;
|
||||
unsigned long SavedTotXLen;
|
||||
|
|
|
@ -314,8 +314,7 @@ struct scsi_core {
|
|||
struct list_head task_queue;
|
||||
int task_queue_size;
|
||||
|
||||
struct semaphore queue_thread_sema;
|
||||
int queue_thread_kill;
|
||||
struct task_struct *queue_thread;
|
||||
};
|
||||
|
||||
struct sas_ha_event {
|
||||
|
|
Loading…
Reference in New Issue