From ea09bcc9c298d3057270abd78a973fc678d55c4c Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Sat, 23 May 2009 11:43:37 -0400 Subject: sd: Physical block size and alignment support Extract physical block size and lowest aligned LBA from READ CAPACITY(16) response and adjust queue parameters. Report physical block size and alignment when applicable. [jejb: fix up trailing whitespace] Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 23 +++++++++++++++++++++-- drivers/scsi/sd.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 878b17a9af30..a86064b6458d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1307,6 +1307,7 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, int sense_valid = 0; int the_result; int retries = 3; + unsigned int alignment; unsigned long long lba; unsigned sector_size; @@ -1358,6 +1359,16 @@ static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp, return -EOVERFLOW; } + /* Logical blocks per physical block exponent */ + sdkp->hw_sector_size = (1 << (buffer[13] & 0xf)) * sector_size; + + /* Lowest aligned logical block */ + alignment = ((buffer[14] & 0x3f) << 8 | buffer[15]) * sector_size; + blk_queue_alignment_offset(sdp->request_queue, alignment); + if (alignment && sdkp->first_scan) + sd_printk(KERN_NOTICE, sdkp, + "physical block alignment offset: %u\n", alignment); + sdkp->capacity = lba + 1; return sector_size; } @@ -1409,6 +1420,7 @@ static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp, } sdkp->capacity = lba + 1; + sdkp->hw_sector_size = sector_size; return sector_size; } @@ -1521,11 +1533,17 @@ got_data: string_get_size(sz, STRING_UNITS_10, cap_str_10, sizeof(cap_str_10)); - if (sdkp->first_scan || old_capacity != sdkp->capacity) + if (sdkp->first_scan || old_capacity != sdkp->capacity) { sd_printk(KERN_NOTICE, sdkp, - "%llu %d-byte hardware sectors: (%s/%s)\n", + "%llu %d-byte logical blocks: (%s/%s)\n", (unsigned long long)sdkp->capacity, sector_size, cap_str_10, cap_str_2); + + if (sdkp->hw_sector_size != sector_size) + sd_printk(KERN_NOTICE, sdkp, + "%u-byte physical blocks\n", + sdkp->hw_sector_size); + } } /* Rescale capacity to 512-byte units */ @@ -1538,6 +1556,7 @@ got_data: else if (sector_size == 256) sdkp->capacity >>= 1; + blk_queue_physical_block_size(sdp->request_queue, sdkp->hw_sector_size); sdkp->device->sector_size = sector_size; } diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 708778cf5f06..8474b5bad3fe 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -45,6 +45,7 @@ struct scsi_disk { unsigned int openers; /* protected by BKL for now, yuck */ sector_t capacity; /* size in 512-byte sectors */ u32 index; + unsigned short hw_sector_size; u8 media_present; u8 write_prot; u8 protection_type;/* Data Integrity Field */ -- cgit v1.2.3 From 3821d768912a47ddbd6cab52943a8284df88003c Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Sat, 23 May 2009 11:43:38 -0400 Subject: sd: Detect non-rotational devices Detect non-rotational devices and set the queue flag accordingly. Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a86064b6458d..2148d659c281 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1794,6 +1794,29 @@ void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) return; } +/** + * sd_read_block_characteristics - Query block dev. characteristics + * @disk: disk to query + */ +static void sd_read_block_characteristics(struct scsi_disk *sdkp) +{ + char *buffer; + u16 rot; + + /* Block Device Characteristics VPD */ + buffer = scsi_get_vpd_page(sdkp->device, 0xb1); + + if (buffer == NULL) + return; + + rot = get_unaligned_be16(&buffer[4]); + + if (rot == 1) + queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sdkp->disk->queue); + + kfree(buffer); +} + /** * sd_revalidate_disk - called the first time a new disk is seen, * performs disk spin up, read_capacity, etc. @@ -1831,6 +1854,7 @@ static int sd_revalidate_disk(struct gendisk *disk) */ if (sdkp->media_present) { sd_read_capacity(sdkp, buffer); + sd_read_block_characteristics(sdkp); sd_read_write_protect_flag(sdkp, buffer); sd_read_cache_type(sdkp, buffer); sd_read_app_tag_own(sdkp, buffer); @@ -1953,6 +1977,8 @@ static void sd_probe_async(void *data, async_cookie_t cookie) add_disk(gd); sd_dif_config_host(sdkp); + sd_revalidate_disk(gd); + sd_printk(KERN_NOTICE, sdkp, "Attached SCSI %sdisk\n", sdp->removable ? "removable " : ""); } -- cgit v1.2.3 From d11b6916961d6ec7d7215332cbbe9feec086721d Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Sat, 23 May 2009 11:43:39 -0400 Subject: sd: Block limits VPD support Query the block limits VPD page and adjust queue minimum and optimal I/O sizes. Signed-off-by: Martin K. Petersen Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2148d659c281..e4ef11af18a2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1794,6 +1794,29 @@ void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) return; } +/** + * sd_read_block_limits - Query disk device for preferred I/O sizes. + * @disk: disk to query + */ +static void sd_read_block_limits(struct scsi_disk *sdkp) +{ + unsigned int sector_sz = sdkp->device->sector_size; + char *buffer; + + /* Block Limits VPD */ + buffer = scsi_get_vpd_page(sdkp->device, 0xb0); + + if (buffer == NULL) + return; + + blk_queue_io_min(sdkp->disk->queue, + get_unaligned_be16(&buffer[6]) * sector_sz); + blk_queue_io_opt(sdkp->disk->queue, + get_unaligned_be32(&buffer[12]) * sector_sz); + + kfree(buffer); +} + /** * sd_read_block_characteristics - Query block dev. characteristics * @disk: disk to query @@ -1854,6 +1877,7 @@ static int sd_revalidate_disk(struct gendisk *disk) */ if (sdkp->media_present) { sd_read_capacity(sdkp, buffer); + sd_read_block_limits(sdkp); sd_read_block_characteristics(sdkp); sd_read_write_protect_flag(sdkp, buffer); sd_read_cache_type(sdkp, buffer); -- cgit v1.2.3 From 295ab1b54393aec064533fbc5b483844736ccbf0 Mon Sep 17 00:00:00 2001 From: Karen Xie Date: Mon, 15 Jun 2009 11:15:16 -0700 Subject: cxgb3i: use kref to track ddp usage The iscsi ddp functionality could be used by multiple iscsi entities, add a refcnt to keep track of it, so we would not release it pre-maturely. Signed-off-by: Karen Xie Signed-off-by: James Bottomley --- drivers/scsi/cxgb3i/cxgb3i_ddp.c | 54 ++++++++++++++++++++++++---------------- drivers/scsi/cxgb3i/cxgb3i_ddp.h | 2 ++ 2 files changed, 35 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index 99c912547902..8eb2848403f4 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c @@ -598,30 +598,40 @@ int cxgb3i_adapter_ddp_info(struct t3cdev *tdev, * release all the resource held by the ddp pagepod manager for a given * adapter if needed */ -void cxgb3i_ddp_cleanup(struct t3cdev *tdev) + +static void ddp_cleanup(struct kref *kref) { + struct cxgb3i_ddp_info *ddp = container_of(kref, + struct cxgb3i_ddp_info, + refcnt); int i = 0; + + ddp_log_info("kref release ddp 0x%p, t3dev 0x%p.\n", ddp, ddp->tdev); + + ddp->tdev->ulp_iscsi = NULL; + while (i < ddp->nppods) { + struct cxgb3i_gather_list *gl = ddp->gl_map[i]; + if (gl) { + int npods = (gl->nelem + PPOD_PAGES_MAX - 1) + >> PPOD_PAGES_SHIFT; + ddp_log_info("t3dev 0x%p, ddp %d + %d.\n", + ddp->tdev, i, npods); + kfree(gl); + ddp_free_gl_skb(ddp, i, npods); + i += npods; + } else + i++; + } + cxgb3i_free_big_mem(ddp); +} + +void cxgb3i_ddp_cleanup(struct t3cdev *tdev) +{ struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi; ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp); - - if (ddp) { - tdev->ulp_iscsi = NULL; - while (i < ddp->nppods) { - struct cxgb3i_gather_list *gl = ddp->gl_map[i]; - if (gl) { - int npods = (gl->nelem + PPOD_PAGES_MAX - 1) - >> PPOD_PAGES_SHIFT; - ddp_log_info("t3dev 0x%p, ddp %d + %d.\n", - tdev, i, npods); - kfree(gl); - ddp_free_gl_skb(ddp, i, npods); - i += npods; - } else - i++; - } - cxgb3i_free_big_mem(ddp); - } + if (ddp) + kref_put(&ddp->refcnt, ddp_cleanup); } /** @@ -631,12 +641,13 @@ void cxgb3i_ddp_cleanup(struct t3cdev *tdev) */ static void ddp_init(struct t3cdev *tdev) { - struct cxgb3i_ddp_info *ddp; + struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi; struct ulp_iscsi_info uinfo; unsigned int ppmax, bits; int i, err; - if (tdev->ulp_iscsi) { + if (ddp) { + kref_get(&ddp->refcnt); ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n", tdev, tdev->ulp_iscsi); return; @@ -670,6 +681,7 @@ static void ddp_init(struct t3cdev *tdev) ppmax * sizeof(struct cxgb3i_gather_list *)); spin_lock_init(&ddp->map_lock); + kref_init(&ddp->refcnt); ddp->tdev = tdev; ddp->pdev = uinfo.pdev; diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h index 0d296de7cf32..87dd56b422bf 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h @@ -54,6 +54,7 @@ struct cxgb3i_gather_list { * struct cxgb3i_ddp_info - cxgb3i direct data placement for pdu payload * * @list: list head to link elements + * @refcnt: ref. count * @tdev: pointer to t3cdev used by cxgb3 driver * @max_txsz: max tx packet size for ddp * @max_rxsz: max rx packet size for ddp @@ -70,6 +71,7 @@ struct cxgb3i_gather_list { */ struct cxgb3i_ddp_info { struct list_head list; + struct kref refcnt; struct t3cdev *tdev; struct pci_dev *pdev; unsigned int max_txsz; -- cgit v1.2.3 From 9194c6264040d71f851236437a392594b26e5b91 Mon Sep 17 00:00:00 2001 From: Karen Xie Date: Mon, 15 Jun 2009 11:15:16 -0700 Subject: cxgb3i: suppot of different kernel page sizes The default kernel pages supported are 4K, 8K, 16K, and 64K. Re-calculate entries if PAGE_SIZE is not one of the defaults. Signed-off-by: Karen Xie Signed-off-by: James Bottomley --- drivers/scsi/cxgb3i/cxgb3i_ddp.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c index 8eb2848403f4..344fd53b9954 100644 --- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c +++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c @@ -206,6 +206,31 @@ int cxgb3i_ddp_find_page_index(unsigned long pgsz) return DDP_PGIDX_MAX; } +/** + * cxgb3i_ddp_adjust_page_table - adjust page table with PAGE_SIZE + * return the ddp page index, if no match is found return DDP_PGIDX_MAX. + */ +int cxgb3i_ddp_adjust_page_table(void) +{ + int i; + unsigned int base_order, order; + + if (PAGE_SIZE < (1UL << ddp_page_shift[0])) { + ddp_log_info("PAGE_SIZE 0x%lx too small, min. 0x%lx.\n", + PAGE_SIZE, 1UL << ddp_page_shift[0]); + return -EINVAL; + } + + base_order = get_order(1UL << ddp_page_shift[0]); + order = get_order(1 << PAGE_SHIFT); + for (i = 0; i < DDP_PGIDX_MAX; i++) { + /* first is the kernel page size, then just doubling the size */ + ddp_page_order[i] = order - base_order + i; + ddp_page_shift[i] = PAGE_SHIFT + i; + } + return 0; +} + static inline void ddp_gl_unmap(struct pci_dev *pdev, struct cxgb3i_gather_list *gl) { @@ -727,6 +752,17 @@ void cxgb3i_ddp_init(struct t3cdev *tdev) { if (page_idx == DDP_PGIDX_MAX) { page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE); + + if (page_idx == DDP_PGIDX_MAX) { + ddp_log_info("system PAGE_SIZE %lu, update hw.\n", + PAGE_SIZE); + if (cxgb3i_ddp_adjust_page_table() < 0) { + ddp_log_info("PAGE_SIZE %lu, ddp disabled.\n", + PAGE_SIZE); + return; + } + page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE); + } ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n", PAGE_SIZE, page_idx); } -- cgit v1.2.3 From d355e57d58193b89283b0c8153649f0427b0bdad Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 15 Jun 2009 22:11:08 -0500 Subject: libiscsi: don't run scsi eh if iscsi task is making progress If we are sending or receiving data for the task successfully do not run the scsi eh, because we know the task is making progress. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 62 +++++++++++++++++++++++++++++++++++---------- drivers/scsi/libiscsi_tcp.c | 6 +++-- include/scsi/libiscsi.h | 4 +++ 3 files changed, 57 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 59908aead531..b55b7991d5fa 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -954,6 +954,7 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, task = iscsi_itt_to_ctask(conn, hdr->itt); if (!task) return ISCSI_ERR_BAD_ITT; + task->last_xfer = jiffies; break; case ISCSI_OP_R2T: /* @@ -1192,10 +1193,12 @@ static int iscsi_xmit_task(struct iscsi_conn *conn) spin_unlock_bh(&conn->session->lock); rc = conn->session->tt->xmit_task(task); spin_lock_bh(&conn->session->lock); - __iscsi_put_task(task); - if (!rc) + if (!rc) { /* done with this task */ + task->last_xfer = jiffies; conn->task = NULL; + } + __iscsi_put_task(task); return rc; } @@ -1361,6 +1364,9 @@ static inline struct iscsi_task *iscsi_alloc_task(struct iscsi_conn *conn, task->state = ISCSI_TASK_PENDING; task->conn = conn; task->sc = sc; + task->have_checked_conn = false; + task->last_timeout = jiffies; + task->last_xfer = jiffies; INIT_LIST_HEAD(&task->running); return task; } @@ -1716,17 +1722,18 @@ static int iscsi_has_ping_timed_out(struct iscsi_conn *conn) return 0; } -static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) +static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) { + enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; + struct iscsi_task *task = NULL; struct iscsi_cls_session *cls_session; struct iscsi_session *session; struct iscsi_conn *conn; - enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED; - cls_session = starget_to_session(scsi_target(scmd->device)); + cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; - ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", scmd); + ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", sc); spin_lock(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { @@ -1745,6 +1752,26 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) goto done; } + task = (struct iscsi_task *)sc->SCp.ptr; + if (!task) + goto done; + /* + * If we have sent (at least queued to the network layer) a pdu or + * recvd one for the task since the last timeout ask for + * more time. If on the next timeout we have not made progress + * we can check if it is the task or connection when we send the + * nop as a ping. + */ + if (time_after_eq(task->last_xfer, task->last_timeout)) { + ISCSI_DBG_CONN(conn, "Command making progress. Asking " + "scsi-ml for more time to complete. " + "Last data recv at %lu. Last timeout was at " + "%lu\n.", task->last_xfer, task->last_timeout); + task->have_checked_conn = false; + rc = BLK_EH_RESET_TIMER; + goto done; + } + if (!conn->recv_timeout && !conn->ping_timeout) goto done; /* @@ -1755,20 +1782,29 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd) rc = BLK_EH_RESET_TIMER; goto done; } + + /* Assumes nop timeout is shorter than scsi cmd timeout */ + if (task->have_checked_conn) + goto done; + /* - * if we are about to check the transport then give the command - * more time + * Checking the transport already or nop from a cmd timeout still + * running */ - if (time_before_eq(conn->last_recv + (conn->recv_timeout * HZ), - jiffies)) { + if (conn->ping_task) { + task->have_checked_conn = true; rc = BLK_EH_RESET_TIMER; goto done; } - /* if in the middle of checking the transport then give us more time */ - if (conn->ping_task) - rc = BLK_EH_RESET_TIMER; + /* Make sure there is a transport check done */ + iscsi_send_nopout(conn, NULL); + task->have_checked_conn = true; + rc = BLK_EH_RESET_TIMER; + done: + if (task) + task->last_timeout = jiffies; spin_unlock(&session->lock); ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? "timer reset" : "nh"); diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index 2bc07090321d..2e0746d70303 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -686,6 +686,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) "offset=%d, datalen=%d)\n", tcp_task->data_offset, tcp_conn->in.datalen); + task->last_xfer = jiffies; rc = iscsi_segment_seek_sg(&tcp_conn->in.segment, sdb->table.sgl, sdb->table.nents, @@ -713,9 +714,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) rc = ISCSI_ERR_BAD_ITT; else if (ahslen) rc = ISCSI_ERR_AHSLEN; - else if (task->sc->sc_data_direction == DMA_TO_DEVICE) + else if (task->sc->sc_data_direction == DMA_TO_DEVICE) { + task->last_xfer = jiffies; rc = iscsi_tcp_r2t_rsp(conn, task); - else + } else rc = ISCSI_ERR_PROTO; spin_unlock(&conn->session->lock); break; diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index 196525cd402f..61afeb59a836 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -125,6 +125,10 @@ struct iscsi_task { struct scsi_cmnd *sc; /* associated SCSI cmd*/ struct iscsi_conn *conn; /* used connection */ + /* data processing tracking */ + unsigned long last_xfer; + unsigned long last_timeout; + bool have_checked_conn; /* state set/tested under session->lock */ int state; atomic_t refcount; -- cgit v1.2.3 From 32382492eb18e8e20be382a1743d0c08469d1e84 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Mon, 15 Jun 2009 22:11:09 -0500 Subject: iscsi_tcp: propogate EAGAIN from sendpage to libiscsi The net layer might return -EAGAIN because it could not get space/mem within the sock sndtimeo or becuase the tcp/ip connection was down. For the latter we do not want to retry because the conn/session should just be shutdown and restarted. libiscsi knows the state of the session recovery so propogate this error to that layer. It will either do iscsi recovery or have us retry the operation. Right now if we have partially sent a pdu we would always retry the IO xmit slowing down recovery. Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/iscsi_tcp.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index b7c092d63bbe..518dbd91df85 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c @@ -253,8 +253,6 @@ static int iscsi_sw_tcp_xmit_segment(struct iscsi_tcp_conn *tcp_conn, if (r < 0) { iscsi_tcp_segment_unmap(segment); - if (copied || r == -EAGAIN) - break; return r; } copied += r; @@ -275,11 +273,17 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn) while (1) { rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment); - if (rc < 0) { + /* + * We may not have been able to send data because the conn + * is getting stopped. libiscsi will know so propogate err + * for it to do the right thing. + */ + if (rc == -EAGAIN) + return rc; + else if (rc < 0) { rc = ISCSI_ERR_XMIT_FAILED; goto error; - } - if (rc == 0) + } else if (rc == 0) break; consumed += rc; -- cgit v1.2.3 From bd2199d417313a056d4d2b2bac852231e1b50a4e Mon Sep 17 00:00:00 2001 From: Erez Zilber Date: Mon, 15 Jun 2009 22:11:10 -0500 Subject: libiscsi: add conn and scsi eh log debug flags Allow the user to control the debug logs in libiscsi. We will now have a module param for connection, session & error handling. [Mike Christie - Fixed up to compile on current code and added missing ISCSI_DBG_EH conversions] Signed-off-by: Erez Zilber Signed-off-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 109 +++++++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index b55b7991d5fa..716cc344c5df 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -38,15 +38,30 @@ #include #include -static int iscsi_dbg_lib; -module_param_named(debug_libiscsi, iscsi_dbg_lib, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug_libiscsi, "Turn on debugging for libiscsi module. " - "Set to 1 to turn on, and zero to turn off. Default " - "is off."); +static int iscsi_dbg_lib_conn; +module_param_named(debug_libiscsi_conn, iscsi_dbg_lib_conn, int, + S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug_libiscsi_conn, + "Turn on debugging for connections in libiscsi module. " + "Set to 1 to turn on, and zero to turn off. Default is off."); + +static int iscsi_dbg_lib_session; +module_param_named(debug_libiscsi_session, iscsi_dbg_lib_session, int, + S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug_libiscsi_session, + "Turn on debugging for sessions in libiscsi module. " + "Set to 1 to turn on, and zero to turn off. Default is off."); + +static int iscsi_dbg_lib_eh; +module_param_named(debug_libiscsi_eh, iscsi_dbg_lib_eh, int, + S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug_libiscsi_eh, + "Turn on debugging for error handling in libiscsi module. " + "Set to 1 to turn on, and zero to turn off. Default is off."); #define ISCSI_DBG_CONN(_conn, dbg_fmt, arg...) \ do { \ - if (iscsi_dbg_lib) \ + if (iscsi_dbg_lib_conn) \ iscsi_conn_printk(KERN_INFO, _conn, \ "%s " dbg_fmt, \ __func__, ##arg); \ @@ -54,7 +69,15 @@ MODULE_PARM_DESC(debug_libiscsi, "Turn on debugging for libiscsi module. " #define ISCSI_DBG_SESSION(_session, dbg_fmt, arg...) \ do { \ - if (iscsi_dbg_lib) \ + if (iscsi_dbg_lib_session) \ + iscsi_session_printk(KERN_INFO, _session, \ + "%s " dbg_fmt, \ + __func__, ##arg); \ + } while (0); + +#define ISCSI_DBG_EH(_session, dbg_fmt, arg...) \ + do { \ + if (iscsi_dbg_lib_eh) \ iscsi_session_printk(KERN_INFO, _session, \ "%s " dbg_fmt, \ __func__, ##arg); \ @@ -1561,10 +1584,10 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->lock); if (session->state == ISCSI_STATE_TERMINATE) { failed: - iscsi_session_printk(KERN_INFO, session, - "failing target reset: Could not log " - "back into target [age %d]\n", - session->age); + ISCSI_DBG_EH(session, + "failing target reset: Could not log back into " + "target [age %d]\n", + session->age); spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); return FAILED; @@ -1578,7 +1601,7 @@ failed: */ iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); - ISCSI_DBG_SESSION(session, "wait for relogin\n"); + ISCSI_DBG_EH(session, "wait for relogin\n"); wait_event_interruptible(conn->ehwait, session->state == ISCSI_STATE_TERMINATE || session->state == ISCSI_STATE_LOGGED_IN || @@ -1588,10 +1611,10 @@ failed: mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); - if (session->state == ISCSI_STATE_LOGGED_IN) - iscsi_session_printk(KERN_INFO, session, - "target reset succeeded\n"); - else + if (session->state == ISCSI_STATE_LOGGED_IN) { + ISCSI_DBG_EH(session, + "target reset succeeded\n"); + } else goto failed; spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); @@ -1607,7 +1630,7 @@ static void iscsi_tmf_timedout(unsigned long data) spin_lock(&session->lock); if (conn->tmf_state == TMF_QUEUED) { conn->tmf_state = TMF_TIMEDOUT; - ISCSI_DBG_SESSION(session, "tmf timedout\n"); + ISCSI_DBG_EH(session, "tmf timedout\n"); /* unblock eh_abort() */ wake_up(&conn->ehwait); } @@ -1627,7 +1650,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, spin_unlock_bh(&session->lock); iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); spin_lock_bh(&session->lock); - ISCSI_DBG_SESSION(session, "tmf exec failure\n"); + ISCSI_DBG_EH(session, "tmf exec failure\n"); return -EPERM; } conn->tmfcmd_pdus_cnt++; @@ -1635,7 +1658,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, conn->tmf_timer.function = iscsi_tmf_timedout; conn->tmf_timer.data = (unsigned long)conn; add_timer(&conn->tmf_timer); - ISCSI_DBG_SESSION(session, "tmf set timeout\n"); + ISCSI_DBG_EH(session, "tmf set timeout\n"); spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); @@ -1733,7 +1756,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; - ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", sc); + ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc); spin_lock(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) { @@ -1763,10 +1786,10 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc) * nop as a ping. */ if (time_after_eq(task->last_xfer, task->last_timeout)) { - ISCSI_DBG_CONN(conn, "Command making progress. Asking " - "scsi-ml for more time to complete. " - "Last data recv at %lu. Last timeout was at " - "%lu\n.", task->last_xfer, task->last_timeout); + ISCSI_DBG_EH(session, "Command making progress. Asking " + "scsi-ml for more time to complete. " + "Last data recv at %lu. Last timeout was at " + "%lu\n.", task->last_xfer, task->last_timeout); task->have_checked_conn = false; rc = BLK_EH_RESET_TIMER; goto done; @@ -1806,8 +1829,8 @@ done: if (task) task->last_timeout = jiffies; spin_unlock(&session->lock); - ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? - "timer reset" : "nh"); + ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ? + "timer reset" : "nh"); return rc; } @@ -1877,7 +1900,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; - ISCSI_DBG_SESSION(session, "aborting sc %p\n", sc); + ISCSI_DBG_EH(session, "aborting sc %p\n", sc); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); @@ -1886,8 +1909,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) * got the command. */ if (!sc->SCp.ptr) { - ISCSI_DBG_SESSION(session, "sc never reached iscsi layer or " - "it completed.\n"); + ISCSI_DBG_EH(session, "sc never reached iscsi layer or " + "it completed.\n"); spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); return SUCCESS; @@ -1901,7 +1924,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) sc->SCp.phase != session->age) { spin_unlock_bh(&session->lock); mutex_unlock(&session->eh_mutex); - ISCSI_DBG_SESSION(session, "failing abort due to dropped " + ISCSI_DBG_EH(session, "failing abort due to dropped " "session.\n"); return FAILED; } @@ -1911,13 +1934,12 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) age = session->age; task = (struct iscsi_task *)sc->SCp.ptr; - ISCSI_DBG_SESSION(session, "aborting [sc %p itt 0x%x]\n", - sc, task->itt); + ISCSI_DBG_EH(session, "aborting [sc %p itt 0x%x]\n", + sc, task->itt); /* task completed before time out */ if (!task->sc) { - ISCSI_DBG_SESSION(session, "sc completed while abort in " - "progress\n"); + ISCSI_DBG_EH(session, "sc completed while abort in progress\n"); goto success; } @@ -1966,8 +1988,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) if (!sc->SCp.ptr) { conn->tmf_state = TMF_INITIAL; /* task completed before tmf abort response */ - ISCSI_DBG_SESSION(session, "sc completed while abort " - "in progress\n"); + ISCSI_DBG_EH(session, "sc completed while abort in " + "progress\n"); goto success; } /* fall through */ @@ -1979,16 +2001,16 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) success: spin_unlock_bh(&session->lock); success_unlocked: - ISCSI_DBG_SESSION(session, "abort success [sc %p itt 0x%x]\n", - sc, task->itt); + ISCSI_DBG_EH(session, "abort success [sc %p itt 0x%x]\n", + sc, task->itt); mutex_unlock(&session->eh_mutex); return SUCCESS; failed: spin_unlock_bh(&session->lock); failed_unlocked: - ISCSI_DBG_SESSION(session, "abort failed [sc %p itt 0x%x]\n", sc, - task ? task->itt : 0); + ISCSI_DBG_EH(session, "abort failed [sc %p itt 0x%x]\n", sc, + task ? task->itt : 0); mutex_unlock(&session->eh_mutex); return FAILED; } @@ -2015,8 +2037,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; - ISCSI_DBG_SESSION(session, "LU Reset [sc %p lun %u]\n", - sc, sc->device->lun); + ISCSI_DBG_EH(session, "LU Reset [sc %p lun %u]\n", sc, sc->device->lun); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->lock); @@ -2070,8 +2091,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) unlock: spin_unlock_bh(&session->lock); done: - ISCSI_DBG_SESSION(session, "dev reset result = %s\n", - rc == SUCCESS ? "SUCCESS" : "FAILED"); + ISCSI_DBG_EH(session, "dev reset result = %s\n", + rc == SUCCESS ? "SUCCESS" : "FAILED"); mutex_unlock(&session->eh_mutex); return rc; } -- cgit v1.2.3 From 93bdcba5a7e55307e27671594c3cd8b4669b9e7a Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Wed, 17 Jun 2009 15:10:10 +0900 Subject: scsi_transport_sas: needs to call blk_end_request_all for SMP requests We need to call blk_end_request_all to complete SMP requests properly. Signed-off-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_sas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index d606452297cf..0895d3c71b03 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -173,9 +173,9 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, ret = handler(shost, rphy, req); req->errors = ret; - spin_lock_irq(q->queue_lock); + blk_end_request_all(req, ret); - req->end_io(req, ret); + spin_lock_irq(q->queue_lock); } } -- cgit v1.2.3 From 30c9afa6cc477f6f21f8a0b36f3b81080941a0c9 Mon Sep 17 00:00:00 2001 From: Joe Eykholt Date: Mon, 15 Jun 2009 23:22:14 -0700 Subject: fix race that can give duplicate host number Just once, two fcoe instances got the same host number from scsi_add_host(). Use atomic_t and atomic_inc_return() to get next host number. Subtract 1, so that scsi_host still starts with 0. [jejb: added comment about unusual subtraction] Signed-off-by: Joe Eykholt Signed-off-by: James Bottomley --- drivers/scsi/hosts.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 89d41a424b33..5fd2da494d08 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -40,7 +40,7 @@ #include "scsi_logging.h" -static int scsi_host_next_hn; /* host_no for next new host */ +static atomic_t scsi_host_next_hn; /* host_no for next new host */ static void scsi_host_cls_release(struct device *dev) @@ -333,7 +333,11 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) mutex_init(&shost->scan_mutex); - shost->host_no = scsi_host_next_hn++; /* XXX(hch): still racy */ + /* + * subtract one because we increment first then return, but we need to + * know what the next host number was before increment + */ + shost->host_no = atomic_inc_return(&scsi_host_next_hn) - 1; shost->dma_channel = 0xff; /* These three are default values which can be overridden */ -- cgit v1.2.3 From 27dc9c5a3d652b0d55ab9ab396dcce9f13bc77c3 Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Wed, 17 Jun 2009 10:30:28 -0700 Subject: qla2xxx: Fixed a bug in number of response queue creation logic. Cc: stable@kernel.org Signed-off-by: Anirban Chakraborty Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index dcf011679c8b..f0396e79b6fa 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1663,7 +1663,7 @@ skip_pio: /* queue 0 uses two msix vectors */ if (ql2xmultique_tag) { cpus = num_online_cpus(); - ha->max_rsp_queues = (ha->msix_count - 1 - cpus) ? + ha->max_rsp_queues = (ha->msix_count - 1 > cpus) ? (cpus + 1) : (ha->msix_count - 1); ha->max_req_queues = 2; } else if (ql2xmaxqueues > 1) { -- cgit v1.2.3 From 1bb395485160d203a726a19e4fcb1a154748d804 Mon Sep 17 00:00:00 2001 From: Harish Zunjarrao Date: Wed, 17 Jun 2009 10:30:29 -0700 Subject: qla2xxx: Correct iiDMA-update calling conventions. * To set iiDMA speeds for ISP81XX, bits 5-0 are used whereas for other older ISPs bits 2-0 are used. * Pass proper VP index Signed-off-by: Harish Zunjarrao Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_mbx.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 262026129325..f2ce8e3cc91b 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2301,7 +2301,7 @@ qla2x00_iidma_fcport(scsi_qla_host_t *vha, fc_port_t *fcport) static char *link_speeds[] = { "1", "2", "?", "4", "8", "10" }; char *link_speed; int rval; - uint16_t mb[6]; + uint16_t mb[4]; struct qla_hw_data *ha = vha->hw; if (!IS_IIDMA_CAPABLE(ha)) diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 451ece0760b0..779ce14e9a2a 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2697,10 +2697,13 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, mcp->mb[0] = MBC_PORT_PARAMS; mcp->mb[1] = loop_id; mcp->mb[2] = BIT_0; - mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0); - mcp->mb[4] = mcp->mb[5] = 0; - mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; - mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_1|MBX_0; + if (IS_QLA81XX(vha->hw)) + mcp->mb[3] = port_speed & (BIT_5|BIT_4|BIT_3|BIT_2|BIT_1|BIT_0); + else + mcp->mb[3] = port_speed & (BIT_2|BIT_1|BIT_0); + mcp->mb[9] = vha->vp_idx; + mcp->out_mb = MBX_9|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_3|MBX_1|MBX_0; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); @@ -2710,8 +2713,6 @@ qla2x00_set_idma_speed(scsi_qla_host_t *vha, uint16_t loop_id, mb[0] = mcp->mb[0]; mb[1] = mcp->mb[1]; mb[3] = mcp->mb[3]; - mb[4] = mcp->mb[4]; - mb[5] = mcp->mb[5]; } if (rval != QLA_SUCCESS) { -- cgit v1.2.3 From 9d2683c05ce57b4a0231e028927bf1197e8324a8 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 Jun 2009 10:30:30 -0700 Subject: qla2xxx: Limit querying to supported mailbox-registers while reading FW state. Pre-ISP24xx chips have dedicated uses for mailbox 4 and 5 which software should typically not query nor update. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_mbx.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 779ce14e9a2a..fe69f3057671 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -1267,17 +1267,22 @@ qla2x00_get_firmware_state(scsi_qla_host_t *vha, uint16_t *states) mcp->mb[0] = MBC_GET_FIRMWARE_STATE; mcp->out_mb = MBX_0; - mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + if (IS_FWI2_CAPABLE(vha->hw)) + mcp->in_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0; + else + mcp->in_mb = MBX_1|MBX_0; mcp->tov = MBX_TOV_SECONDS; mcp->flags = 0; rval = qla2x00_mailbox_command(vha, mcp); /* Return firmware states. */ states[0] = mcp->mb[1]; - states[1] = mcp->mb[2]; - states[2] = mcp->mb[3]; - states[3] = mcp->mb[4]; - states[4] = mcp->mb[5]; + if (IS_FWI2_CAPABLE(vha->hw)) { + states[1] = mcp->mb[2]; + states[2] = mcp->mb[3]; + states[3] = mcp->mb[4]; + states[4] = mcp->mb[5]; + } if (rval != QLA_SUCCESS) { /*EMPTY*/ -- cgit v1.2.3 From e18e963b7e533149676b5d387d0a56160df9f111 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 Jun 2009 10:30:31 -0700 Subject: qla2xxx: Correct (again) overflow during dump-processing on large-memory ISP23xx parts. Commit 7b867cf76fbcc8d77867cbec6f509f71dce8a98f ([SCSI] qla2xxx: Refactor qla data structures) inadvertently reverted e792121ec85672c1fa48f79d13986a3f4f56c590 ([SCSI] qla2xxx: Correct overflow during dump-processing on large-memory ISP23xx parts.). Cc: stable@kernel.org Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index 4a990f4da4ea..cca8e4ab0372 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -216,7 +216,7 @@ qla24xx_soft_reset(struct qla_hw_data *ha) static int qla2xxx_dump_ram(struct qla_hw_data *ha, uint32_t addr, uint16_t *ram, - uint16_t ram_words, void **nxt) + uint32_t ram_words, void **nxt) { int rval; uint32_t cnt, stat, timer, words, idx; -- cgit v1.2.3 From e0420029dedb867e5c2c044a0737338a7e9cec0b Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 17 Jun 2009 10:30:32 -0700 Subject: qla2xxx: Update version number to 8.03.01-k4. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index b63feaf43126..84369705a9ad 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.03.01-k3" +#define QLA2XXX_VERSION "8.03.01-k4" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 3 -- cgit v1.2.3 From 598fa4b775d064d4656132c78d9a312eb1d2f91f Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 17 Jun 2009 15:01:58 -0400 Subject: enhance device info matching for multiple tables The current scsi_devinfo.c matching routines use a single table for the global blacklist. However, we're developing a need to blacklist from specific transports too (notably some tape drives using SPI which don't respond well to high speed protocols). Instead of developing separate blacklist matching for each transport class needing it, enhance the current list matching to permit multiple lists. Signed-off-by: James Bottomley --- drivers/scsi/scsi_devinfo.c | 247 ++++++++++++++++++++++++++++++++++++++++---- drivers/scsi/scsi_priv.h | 15 +++ 2 files changed, 240 insertions(+), 22 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 8821df9a277b..93c2622cb969 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -24,6 +24,13 @@ struct scsi_dev_info_list { unsigned compatible; /* for use with scsi_static_device_list entries */ }; +struct scsi_dev_info_list_table { + struct list_head node; /* our node for being on the master list */ + struct list_head scsi_dev_info_list; /* head of dev info list */ + const char *name; /* name of list for /proc (NULL for global) */ + int key; /* unique numeric identifier */ +}; + static const char spaces[] = " "; /* 16 of them */ static unsigned scsi_default_dev_flags; @@ -247,6 +254,22 @@ static struct { { NULL, NULL, NULL, 0 }, }; +static struct scsi_dev_info_list_table *scsi_devinfo_lookup_by_key(int key) +{ + struct scsi_dev_info_list_table *devinfo_table; + int found = 0; + + list_for_each_entry(devinfo_table, &scsi_dev_info_list, node) + if (devinfo_table->key == key) { + found = 1; + break; + } + if (!found) + return ERR_PTR(-EINVAL); + + return devinfo_table; +} + /* * scsi_strcpy_devinfo: called from scsi_dev_info_list_add to copy into * devinfo vendor and model strings. @@ -295,8 +318,39 @@ static void scsi_strcpy_devinfo(char *name, char *to, size_t to_length, **/ static int scsi_dev_info_list_add(int compatible, char *vendor, char *model, char *strflags, int flags) +{ + return scsi_dev_info_list_add_keyed(compatible, vendor, model, + strflags, flags, + SCSI_DEVINFO_GLOBAL); +} + +/** + * scsi_dev_info_list_add_keyed - add one dev_info list entry. + * @compatible: if true, null terminate short strings. Otherwise space pad. + * @vendor: vendor string + * @model: model (product) string + * @strflags: integer string + * @flags: if strflags NULL, use this flag value + * @key: specify list to use + * + * Description: + * Create and add one dev_info entry for @vendor, @model, + * @strflags or @flag in list specified by @key. If @compatible, + * add to the tail of the list, do not space pad, and set + * devinfo->compatible. The scsi_static_device_list entries are + * added with @compatible 1 and @clfags NULL. + * + * Returns: 0 OK, -error on failure. + **/ +int scsi_dev_info_list_add_keyed(int compatible, char *vendor, char *model, + char *strflags, int flags, int key) { struct scsi_dev_info_list *devinfo; + struct scsi_dev_info_list_table *devinfo_table = + scsi_devinfo_lookup_by_key(key); + + if (IS_ERR(devinfo_table)) + return PTR_ERR(devinfo_table); devinfo = kmalloc(sizeof(*devinfo), GFP_KERNEL); if (!devinfo) { @@ -317,12 +371,15 @@ static int scsi_dev_info_list_add(int compatible, char *vendor, char *model, devinfo->compatible = compatible; if (compatible) - list_add_tail(&devinfo->dev_info_list, &scsi_dev_info_list); + list_add_tail(&devinfo->dev_info_list, + &devinfo_table->scsi_dev_info_list); else - list_add(&devinfo->dev_info_list, &scsi_dev_info_list); + list_add(&devinfo->dev_info_list, + &devinfo_table->scsi_dev_info_list); return 0; } +EXPORT_SYMBOL(scsi_dev_info_list_add_keyed); /** * scsi_dev_info_list_add_str - parse dev_list and add to the scsi_dev_info_list. @@ -382,22 +439,48 @@ static int scsi_dev_info_list_add_str(char *dev_list) * @model: model name * * Description: - * Search the scsi_dev_info_list for an entry matching @vendor and - * @model, if found, return the matching flags value, else return - * the host or global default settings. Called during scan time. + * Search the global scsi_dev_info_list (specified by list zero) + * for an entry matching @vendor and @model, if found, return the + * matching flags value, else return the host or global default + * settings. Called during scan time. **/ int scsi_get_device_flags(struct scsi_device *sdev, const unsigned char *vendor, const unsigned char *model) +{ + return scsi_get_device_flags_keyed(sdev, vendor, model, + SCSI_DEVINFO_GLOBAL); +} + + +/** + * get_device_flags_keyed - get device specific flags from the dynamic device list. + * @sdev: &scsi_device to get flags for + * @vendor: vendor name + * @model: model name + * @key: list to look up + * + * Description: + * Search the scsi_dev_info_list specified by @key for an entry + * matching @vendor and @model, if found, return the matching + * flags value, else return the host or global default settings. + * Called during scan time. + **/ +int scsi_get_device_flags_keyed(struct scsi_device *sdev, + const unsigned char *vendor, + const unsigned char *model, + int key) { struct scsi_dev_info_list *devinfo; - unsigned int bflags; + struct scsi_dev_info_list_table *devinfo_table; + + devinfo_table = scsi_devinfo_lookup_by_key(key); - bflags = sdev->sdev_bflags; - if (!bflags) - bflags = scsi_default_dev_flags; + if (IS_ERR(devinfo_table)) + return PTR_ERR(devinfo_table); - list_for_each_entry(devinfo, &scsi_dev_info_list, dev_info_list) { + list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list, + dev_info_list) { if (devinfo->compatible) { /* * Behave like the older version of get_device_flags. @@ -447,32 +530,89 @@ int scsi_get_device_flags(struct scsi_device *sdev, return devinfo->flags; } } - return bflags; + /* nothing found, return nothing */ + if (key != SCSI_DEVINFO_GLOBAL) + return 0; + + /* except for the global list, where we have an exception */ + if (sdev->sdev_bflags) + return sdev->sdev_bflags; + + return scsi_default_dev_flags; } +EXPORT_SYMBOL(scsi_get_device_flags_keyed); #ifdef CONFIG_SCSI_PROC_FS +struct double_list { + struct list_head *top; + struct list_head *bottom; +}; + static int devinfo_seq_show(struct seq_file *m, void *v) { + struct double_list *dl = v; + struct scsi_dev_info_list_table *devinfo_table = + list_entry(dl->top, struct scsi_dev_info_list_table, node); struct scsi_dev_info_list *devinfo = - list_entry(v, struct scsi_dev_info_list, dev_info_list); + list_entry(dl->bottom, struct scsi_dev_info_list, + dev_info_list); + + if (devinfo_table->scsi_dev_info_list.next == dl->bottom && + devinfo_table->name) + seq_printf(m, "[%s]:\n", devinfo_table->name); seq_printf(m, "'%.8s' '%.16s' 0x%x\n", - devinfo->vendor, devinfo->model, devinfo->flags); + devinfo->vendor, devinfo->model, devinfo->flags); return 0; } -static void * devinfo_seq_start(struct seq_file *m, loff_t *pos) +static void *devinfo_seq_start(struct seq_file *m, loff_t *ppos) { - return seq_list_start(&scsi_dev_info_list, *pos); + struct double_list *dl = kmalloc(sizeof(*dl), GFP_KERNEL); + loff_t pos = *ppos; + + if (!dl) + return NULL; + + list_for_each(dl->top, &scsi_dev_info_list) { + struct scsi_dev_info_list_table *devinfo_table = + list_entry(dl->top, struct scsi_dev_info_list_table, + node); + list_for_each(dl->bottom, &devinfo_table->scsi_dev_info_list) + if (pos-- == 0) + return dl; + } + + kfree(dl); + return NULL; } -static void * devinfo_seq_next(struct seq_file *m, void *v, loff_t *pos) +static void *devinfo_seq_next(struct seq_file *m, void *v, loff_t *ppos) { - return seq_list_next(v, &scsi_dev_info_list, pos); + struct double_list *dl = v; + struct scsi_dev_info_list_table *devinfo_table = + list_entry(dl->top, struct scsi_dev_info_list_table, node); + + ++*ppos; + dl->bottom = dl->bottom->next; + while (&devinfo_table->scsi_dev_info_list == dl->bottom) { + dl->top = dl->top->next; + if (dl->top == &scsi_dev_info_list) { + kfree(dl); + return NULL; + } + devinfo_table = list_entry(dl->top, + struct scsi_dev_info_list_table, + node); + dl->bottom = devinfo_table->scsi_dev_info_list.next; + } + + return dl; } static void devinfo_seq_stop(struct seq_file *m, void *v) { + kfree(v); } static const struct seq_operations scsi_devinfo_seq_ops = { @@ -549,19 +689,78 @@ MODULE_PARM_DESC(default_dev_flags, **/ void scsi_exit_devinfo(void) { - struct list_head *lh, *lh_next; - struct scsi_dev_info_list *devinfo; - #ifdef CONFIG_SCSI_PROC_FS remove_proc_entry("scsi/device_info", NULL); #endif - list_for_each_safe(lh, lh_next, &scsi_dev_info_list) { + scsi_dev_info_remove_list(SCSI_DEVINFO_GLOBAL); +} + +/** + * scsi_dev_info_add_list - add a new devinfo list + * @key: key of the list to add + * @name: Name of the list to add (for /proc/scsi/device_info) + * + * Adds the requested list, returns zero on success, -EEXIST if the + * key is already registered to a list, or other error on failure. + */ +int scsi_dev_info_add_list(int key, const char *name) +{ + struct scsi_dev_info_list_table *devinfo_table = + scsi_devinfo_lookup_by_key(key); + + if (!IS_ERR(devinfo_table)) + /* list already exists */ + return -EEXIST; + + devinfo_table = kmalloc(sizeof(*devinfo_table), GFP_KERNEL); + + if (!devinfo_table) + return -ENOMEM; + + INIT_LIST_HEAD(&devinfo_table->node); + INIT_LIST_HEAD(&devinfo_table->scsi_dev_info_list); + devinfo_table->name = name; + devinfo_table->key = key; + list_add_tail(&devinfo_table->node, &scsi_dev_info_list); + + return 0; +} +EXPORT_SYMBOL(scsi_dev_info_add_list); + +/** + * scsi_dev_info_remove_list - destroy an added devinfo list + * @key: key of the list to destroy + * + * Iterates over the entire list first, freeing all the values, then + * frees the list itself. Returns 0 on success or -EINVAL if the key + * can't be found. + */ +int scsi_dev_info_remove_list(int key) +{ + struct list_head *lh, *lh_next; + struct scsi_dev_info_list_table *devinfo_table = + scsi_devinfo_lookup_by_key(key); + + if (IS_ERR(devinfo_table)) + /* no such list */ + return -EINVAL; + + /* remove from the master list */ + list_del(&devinfo_table->node); + + list_for_each_safe(lh, lh_next, &devinfo_table->scsi_dev_info_list) { + struct scsi_dev_info_list *devinfo; + devinfo = list_entry(lh, struct scsi_dev_info_list, dev_info_list); kfree(devinfo); } + kfree(devinfo_table); + + return 0; } +EXPORT_SYMBOL(scsi_dev_info_remove_list); /** * scsi_init_devinfo - set up the dynamic device list. @@ -577,10 +776,14 @@ int __init scsi_init_devinfo(void) #endif int error, i; - error = scsi_dev_info_list_add_str(scsi_dev_flags); + error = scsi_dev_info_add_list(SCSI_DEVINFO_GLOBAL, NULL); if (error) return error; + error = scsi_dev_info_list_add_str(scsi_dev_flags); + if (error) + goto out; + for (i = 0; scsi_static_device_list[i].vendor; i++) { error = scsi_dev_info_list_add(1 /* compatibile */, scsi_static_device_list[i].vendor, diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index fbc83bebdd8e..b4e49cd6e75d 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -39,9 +39,24 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) #endif /* scsi_devinfo.c */ + +/* list of keys for the lists */ +enum { + SCSI_DEVINFO_GLOBAL = 0, +}; + extern int scsi_get_device_flags(struct scsi_device *sdev, const unsigned char *vendor, const unsigned char *model); +extern int scsi_get_device_flags_keyed(struct scsi_device *sdev, + const unsigned char *vendor, + const unsigned char *model, int key); +extern int scsi_dev_info_list_add_keyed(int compatible, char *vendor, + char *model, char *strflags, + int flags, int key); +extern int scsi_dev_info_add_list(int key, const char *name); +extern int scsi_dev_info_remove_list(int key); + extern int __init scsi_init_devinfo(void); extern void scsi_exit_devinfo(void); -- cgit v1.2.3 From 9872b81cf9f4b163e9c558d79e76b832c58a4814 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 17 Jun 2009 15:03:41 -0400 Subject: scsi_transport_spi: use spi target settings instead of inquiry data for DV Right at the moment, we carefully set up the spi_support_xx in the device configuration routines, but then we never actually use the results: we rely on the inquiry strings. If we're going to allow overrides to the inquiry data, we have to rely on our own internal settings. Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_spi.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 654a34fb04cb..00cfb40b5efa 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -833,7 +833,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) return; } - if (!scsi_device_wide(sdev)) { + if (!spi_support_wide(starget)) { spi_max_width(starget) = 0; max_width = 0; } @@ -860,7 +860,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) return; /* device can't handle synchronous */ - if (!scsi_device_sync(sdev) && !scsi_device_dt(sdev)) + if (!spi_support_sync(starget) && !spi_support_dt(starget)) return; /* len == -1 is the signal that we need to ascertain the @@ -876,13 +876,14 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) /* try QAS requests; this should be harmless to set if the * target supports it */ - if (scsi_device_qas(sdev) && spi_max_qas(starget)) { + if (spi_support_qas(starget) && spi_max_qas(starget)) { DV_SET(qas, 1); } else { DV_SET(qas, 0); } - if (scsi_device_ius(sdev) && spi_max_iu(starget) && min_period < 9) { + if (spi_support_ius(starget) && spi_max_iu(starget) && + min_period < 9) { /* This u320 (or u640). Set IU transfers */ DV_SET(iu, 1); /* Then set the optional parameters */ @@ -902,7 +903,7 @@ spi_dv_device_internal(struct scsi_device *sdev, u8 *buffer) i->f->get_signalling(shost); if (spi_signalling(shost) == SPI_SIGNAL_SE || spi_signalling(shost) == SPI_SIGNAL_HVD || - !scsi_device_dt(sdev)) { + !spi_support_dt(starget)) { DV_SET(dt, 0); } else { DV_SET(dt, 1); -- cgit v1.2.3 From a9e0edb687151617fe89cc5ab0086ebfc73ffccb Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Wed, 17 Jun 2009 19:05:05 +0000 Subject: scsi_transport_spi: Blacklist Ultrium-3 tape for IU transfers There have been several bug reports which identified the Ultrium-3 tape as just hanging up on the bus during certain types of IU transfer. The identified culpret is type 0x02 (MULTIPLE COMMAND) transfers. The only way to prevent this tape wedging is to prevent it from using IU transfers at all. So this patch uses the exported blacklist matching technology to recognise the drive and force it not to use IU transfers. Signed-off-by: James Bottomley --- drivers/scsi/scsi_priv.h | 1 + drivers/scsi/scsi_transport_spi.c | 40 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index b4e49cd6e75d..00264aab8c8a 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -43,6 +43,7 @@ static inline void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) /* list of keys for the lists */ enum { SCSI_DEVINFO_GLOBAL = 0, + SCSI_DEVINFO_SPI, }; extern int scsi_get_device_flags(struct scsi_device *sdev, diff --git a/drivers/scsi/scsi_transport_spi.c b/drivers/scsi/scsi_transport_spi.c index 00cfb40b5efa..c25bd9a34e02 100644 --- a/drivers/scsi/scsi_transport_spi.c +++ b/drivers/scsi/scsi_transport_spi.c @@ -46,6 +46,22 @@ #define DV_RETRIES 3 /* should only need at most * two cc/ua clears */ +/* Our blacklist flags */ +enum { + SPI_BLIST_NOIUS = 0x1, +}; + +/* blacklist table, modelled on scsi_devinfo.c */ +static struct { + char *vendor; + char *model; + unsigned flags; +} spi_static_device_list[] __initdata = { + {"HP", "Ultrium 3-SCSI", SPI_BLIST_NOIUS }, + {"IBM", "ULTRIUM-TD3", SPI_BLIST_NOIUS }, + {NULL, NULL, 0} +}; + /* Private data accessors (keep these out of the header file) */ #define spi_dv_in_progress(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_in_progress) #define spi_dv_mutex(x) (((struct spi_transport_attrs *)&(x)->starget_data)->dv_mutex) @@ -207,6 +223,9 @@ static int spi_device_configure(struct transport_container *tc, { struct scsi_device *sdev = to_scsi_device(dev); struct scsi_target *starget = sdev->sdev_target; + unsigned bflags = scsi_get_device_flags_keyed(sdev, &sdev->inquiry[8], + &sdev->inquiry[16], + SCSI_DEVINFO_SPI); /* Populate the target capability fields with the values * gleaned from the device inquiry */ @@ -216,6 +235,10 @@ static int spi_device_configure(struct transport_container *tc, spi_support_dt(starget) = scsi_device_dt(sdev); spi_support_dt_only(starget) = scsi_device_dt_only(sdev); spi_support_ius(starget) = scsi_device_ius(sdev); + if (bflags & SPI_BLIST_NOIUS) { + dev_info(dev, "Information Units disabled by blacklist\n"); + spi_support_ius(starget) = 0; + } spi_support_qas(starget) = scsi_device_qas(sdev); return 0; @@ -1524,7 +1547,21 @@ EXPORT_SYMBOL(spi_release_transport); static __init int spi_transport_init(void) { - int error = transport_class_register(&spi_transport_class); + int error = scsi_dev_info_add_list(SCSI_DEVINFO_SPI, + "SCSI Parallel Transport Class"); + if (!error) { + int i; + + for (i = 0; spi_static_device_list[i].vendor; i++) + scsi_dev_info_list_add_keyed(1, /* compatible */ + spi_static_device_list[i].vendor, + spi_static_device_list[i].model, + NULL, + spi_static_device_list[i].flags, + SCSI_DEVINFO_SPI); + } + + error = transport_class_register(&spi_transport_class); if (error) return error; error = anon_transport_class_register(&spi_device_class); @@ -1536,6 +1573,7 @@ static void __exit spi_transport_exit(void) transport_class_unregister(&spi_transport_class); anon_transport_class_unregister(&spi_device_class); transport_class_unregister(&spi_host_class); + scsi_dev_info_remove_list(SCSI_DEVINFO_SPI); } MODULE_AUTHOR("Martin Hicks"); -- cgit v1.2.3 From 95fecd90397ec1f85eb31ede955d846a86d2077b Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Tue, 16 Jun 2009 15:13:28 -0700 Subject: ipr: add test for MSI interrupt support The return value from pci_enable_msi() can not always be trusted. This patch adds code to generate an interrupt after MSI has been enabled and tests whether or not we can receive and process it. If the tests fails, then fall back to LSI. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++---- drivers/scsi/ipr.h | 6 ++- 2 files changed, 105 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 0f8bc772b112..15ce8e51d5de 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -7367,6 +7367,7 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, INIT_LIST_HEAD(&ioa_cfg->used_res_q); INIT_WORK(&ioa_cfg->work_q, ipr_worker_thread); init_waitqueue_head(&ioa_cfg->reset_wait_q); + init_waitqueue_head(&ioa_cfg->msi_wait_q); ioa_cfg->sdt_state = INACTIVE; if (ipr_enable_cache) ioa_cfg->cache_state = CACHE_ENABLED; @@ -7416,6 +7417,89 @@ ipr_get_chip_cfg(const struct pci_device_id *dev_id) return NULL; } +/** + * ipr_test_intr - Handle the interrupt generated in ipr_test_msi(). + * @pdev: PCI device struct + * + * Description: Simply set the msi_received flag to 1 indicating that + * Message Signaled Interrupts are supported. + * + * Return value: + * 0 on success / non-zero on failure + **/ +static irqreturn_t __devinit ipr_test_intr(int irq, void *devp) +{ + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)devp; + unsigned long lock_flags = 0; + irqreturn_t rc = IRQ_HANDLED; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + + ioa_cfg->msi_received = 1; + wake_up(&ioa_cfg->msi_wait_q); + + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return rc; +} + +/** + * ipr_test_msi - Test for Message Signaled Interrupt (MSI) support. + * @pdev: PCI device struct + * + * Description: The return value from pci_enable_msi() can not always be + * trusted. This routine sets up and initiates a test interrupt to determine + * if the interrupt is received via the ipr_test_intr() service routine. + * If the tests fails, the driver will fall back to LSI. + * + * Return value: + * 0 on success / non-zero on failure + **/ +static int __devinit ipr_test_msi(struct ipr_ioa_cfg *ioa_cfg, + struct pci_dev *pdev) +{ + int rc; + volatile u32 int_reg; + unsigned long lock_flags = 0; + + ENTER; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + init_waitqueue_head(&ioa_cfg->msi_wait_q); + ioa_cfg->msi_received = 0; + ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); + writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.clr_interrupt_mask_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_mask_reg); + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + + rc = request_irq(pdev->irq, ipr_test_intr, 0, IPR_NAME, ioa_cfg); + if (rc) { + dev_err(&pdev->dev, "Can not assign irq %d\n", pdev->irq); + return rc; + } else if (ipr_debug) + dev_info(&pdev->dev, "IRQ assigned: %d\n", pdev->irq); + + writel(IPR_PCII_IO_DEBUG_ACKNOWLEDGE, ioa_cfg->regs.sense_interrupt_reg); + int_reg = readl(ioa_cfg->regs.sense_interrupt_reg); + wait_event_timeout(ioa_cfg->msi_wait_q, ioa_cfg->msi_received, HZ); + ipr_mask_and_clear_interrupts(ioa_cfg, ~IPR_PCII_IOA_TRANS_TO_OPER); + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + if (!ioa_cfg->msi_received) { + /* MSI test failed */ + dev_info(&pdev->dev, "MSI test failed. Falling back to LSI.\n"); + rc = -EOPNOTSUPP; + } else if (ipr_debug) + dev_info(&pdev->dev, "MSI test succeeded.\n"); + + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + + free_irq(pdev->irq, ioa_cfg); + + LEAVE; + + return rc; +} + /** * ipr_probe_ioa - Allocates memory and does first stage of initialization * @pdev: PCI device struct @@ -7441,11 +7525,6 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, goto out; } - if (!(rc = pci_enable_msi(pdev))) - dev_info(&pdev->dev, "MSI enabled\n"); - else if (ipr_debug) - dev_info(&pdev->dev, "Cannot enable MSI\n"); - dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq); host = scsi_host_alloc(&driver_template, sizeof(*ioa_cfg)); @@ -7519,6 +7598,18 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, goto cleanup_nomem; } + /* Enable MSI style interrupts if they are supported. */ + if (!(rc = pci_enable_msi(pdev))) { + rc = ipr_test_msi(ioa_cfg, pdev); + if (rc == -EOPNOTSUPP) + pci_disable_msi(pdev); + else if (rc) + goto out_msi_disable; + else + dev_info(&pdev->dev, "MSI enabled with IRQ: %d\n", pdev->irq); + } else if (ipr_debug) + dev_info(&pdev->dev, "Cannot enable MSI.\n"); + /* Save away PCI config space for use following IOA reset */ rc = pci_save_state(pdev); @@ -7556,7 +7647,9 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, 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); + rc = request_irq(pdev->irq, ipr_isr, + ioa_cfg->msi_received ? 0 : IRQF_SHARED, + IPR_NAME, ioa_cfg); if (rc) { dev_err(&pdev->dev, "Couldn't register IRQ %d! rc=%d\n", @@ -7583,12 +7676,13 @@ cleanup_nolog: ipr_free_mem(ioa_cfg); cleanup_nomem: iounmap(ipr_regs); +out_msi_disable: + pci_disable_msi(pdev); out_release_regions: pci_release_regions(pdev); out_scsi_host_put: scsi_host_put(host); out_disable: - pci_disable_msi(pdev); pci_disable_device(pdev); goto out; } diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 79a3ae4fb2c7..2d9269b26f88 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -37,8 +37,8 @@ /* * Literals */ -#define IPR_DRIVER_VERSION "2.4.2" -#define IPR_DRIVER_DATE "(January 21, 2009)" +#define IPR_DRIVER_VERSION "2.4.3" +#define IPR_DRIVER_DATE "(June 10, 2009)" /* * IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding @@ -1094,6 +1094,7 @@ struct ipr_ioa_cfg { u8 needs_hard_reset:1; u8 dual_raid:1; u8 needs_warm_reset:1; + u8 msi_received:1; u8 revid; @@ -1179,6 +1180,7 @@ struct ipr_ioa_cfg { struct work_struct work_q; wait_queue_head_t reset_wait_q; + wait_queue_head_t msi_wait_q; struct ipr_dump *dump; enum ipr_sdt_state sdt_state; -- cgit v1.2.3 From 1be7bd82bf4c5d9d3efd1de0e2ebe2c5b1db8340 Mon Sep 17 00:00:00 2001 From: Wayne Boyer Date: Wed, 17 Jun 2009 09:55:35 -0700 Subject: ipr: differentiate pci-x and pci-e based adapters MSI has only been tested on and known to work with PCI-E based adapters. This patch adds a field to struct ipr_chip_t to indicate which type of interrupt to use based on what is known about the chip. Signed-off-by: Wayne Boyer Acked-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ipr.c | 32 +++++++++++++++++--------------- drivers/scsi/ipr.h | 4 ++++ 2 files changed, 21 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 15ce8e51d5de..5f045505a1f4 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -131,13 +131,13 @@ static const struct ipr_chip_cfg_t ipr_chip_cfg[] = { }; static const struct ipr_chip_t ipr_chip[] = { - { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, &ipr_chip_cfg[0] }, - { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, &ipr_chip_cfg[1] }, - { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, &ipr_chip_cfg[1] } + { PCI_VENDOR_ID_MYLEX, PCI_DEVICE_ID_IBM_GEMSTONE, IPR_USE_LSI, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CITRINE, IPR_USE_LSI, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN, IPR_USE_LSI, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN, IPR_USE_LSI, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_OBSIDIAN_E, IPR_USE_MSI, &ipr_chip_cfg[0] }, + { PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_SNIPE, IPR_USE_LSI, &ipr_chip_cfg[1] }, + { PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_SCAMP, IPR_USE_LSI, &ipr_chip_cfg[1] } }; static int ipr_max_bus_speeds [] = { @@ -7399,21 +7399,21 @@ static void __devinit ipr_init_ioa_cfg(struct ipr_ioa_cfg *ioa_cfg, } /** - * ipr_get_chip_cfg - Find adapter chip configuration + * ipr_get_chip_info - Find adapter chip information * @dev_id: PCI device id struct * * Return value: - * ptr to chip config on success / NULL on failure + * ptr to chip information on success / NULL on failure **/ -static const struct ipr_chip_cfg_t * __devinit -ipr_get_chip_cfg(const struct pci_device_id *dev_id) +static const struct ipr_chip_t * __devinit +ipr_get_chip_info(const struct pci_device_id *dev_id) { int i; for (i = 0; i < ARRAY_SIZE(ipr_chip); i++) if (ipr_chip[i].vendor == dev_id->vendor && ipr_chip[i].device == dev_id->device) - return ipr_chip[i].cfg; + return &ipr_chip[i]; return NULL; } @@ -7540,14 +7540,16 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, ata_host_init(&ioa_cfg->ata_host, &pdev->dev, sata_port_info.flags, &ipr_sata_ops); - ioa_cfg->chip_cfg = ipr_get_chip_cfg(dev_id); + ioa_cfg->ipr_chip = ipr_get_chip_info(dev_id); - if (!ioa_cfg->chip_cfg) { + if (!ioa_cfg->ipr_chip) { dev_err(&pdev->dev, "Unknown adapter chipset 0x%04X 0x%04X\n", dev_id->vendor, dev_id->device); goto out_scsi_host_put; } + ioa_cfg->chip_cfg = ioa_cfg->ipr_chip->cfg; + if (ipr_transop_timeout) ioa_cfg->transop_timeout = ipr_transop_timeout; else if (dev_id->driver_data & IPR_USE_LONG_TRANSOP_TIMEOUT) @@ -7599,7 +7601,7 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev, } /* Enable MSI style interrupts if they are supported. */ - if (!(rc = pci_enable_msi(pdev))) { + if (ioa_cfg->ipr_chip->intr_type == IPR_USE_MSI && !pci_enable_msi(pdev)) { rc = ipr_test_msi(ioa_cfg, pdev); if (rc == -EOPNOTSUPP) pci_disable_msi(pdev); diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h index 2d9269b26f88..4b63dd6b1c81 100644 --- a/drivers/scsi/ipr.h +++ b/drivers/scsi/ipr.h @@ -1025,6 +1025,9 @@ struct ipr_chip_cfg_t { struct ipr_chip_t { u16 vendor; u16 device; + u16 intr_type; +#define IPR_USE_LSI 0x00 +#define IPR_USE_MSI 0x01 const struct ipr_chip_cfg_t *cfg; }; @@ -1160,6 +1163,7 @@ struct ipr_ioa_cfg { unsigned int transop_timeout; const struct ipr_chip_cfg_t *chip_cfg; + const struct ipr_chip_t *ipr_chip; void __iomem *hdw_dma_regs; /* iomapped PCI memory space */ unsigned long hdw_dma_regs_pci; /* raw PCI memory space */ -- cgit v1.2.3 From 7cbdca23c8a4e6d007b62c9136ba0e5f86e069d0 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 13 Jun 2009 15:51:08 -0500 Subject: Revert "[SCSI] cnic: fix error: implicit declaration of function ‘__symbol_get’" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit bc3bf8fd330ce981ce632a1a4a283eee46838f32. All the commit did was add a second #include of which is the wrong fix. Signed-off-by: James Bottomley --- drivers/net/cnic.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index 44f77eb1180f..a9e2fd35bb41 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -25,8 +25,6 @@ #include #include #include -#include - #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define BCM_VLAN 1 #endif -- cgit v1.2.3 From e2ee3616bc334ab51e68aad6905761ca97f35559 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Sat, 13 Jun 2009 17:43:02 -0700 Subject: cnic: Fix __symbol_get() build error. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ingo molnar reported the error drivers/net/cnic.c:2520: error: implicit declaration of function ‘__symbol_get’ when CONFIG_MODULES is not defined. Fix by using symbol_get() instead. Signed-off-by: Michael Chan Signed-off-by: James Bottomley --- drivers/net/cnic.c | 4 ++-- drivers/net/cnic_if.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c index a9e2fd35bb41..4d1515f45ba2 100644 --- a/drivers/net/cnic.c +++ b/drivers/net/cnic.c @@ -2519,9 +2519,9 @@ static struct cnic_dev *init_bnx2_cnic(struct net_device *dev) struct cnic_dev *cdev; struct cnic_local *cp; struct cnic_eth_dev *ethdev = NULL; - struct cnic_eth_dev *(*probe)(void *) = NULL; + struct cnic_eth_dev *(*probe)(struct net_device *) = NULL; - probe = __symbol_get("bnx2_cnic_probe"); + probe = symbol_get(bnx2_cnic_probe); if (probe) { ethdev = (*probe)(dev); symbol_put_addr(probe); diff --git a/drivers/net/cnic_if.h b/drivers/net/cnic_if.h index 06380963a34e..d1bce27ee99e 100644 --- a/drivers/net/cnic_if.h +++ b/drivers/net/cnic_if.h @@ -296,4 +296,6 @@ extern int cnic_register_driver(int ulp_type, struct cnic_ulp_ops *ulp_ops); extern int cnic_unregister_driver(int ulp_type); +extern struct cnic_eth_dev *bnx2_cnic_probe(struct net_device *dev); + #endif -- cgit v1.2.3 From 895553824ed9d2c1409d4dc6e0db4d6dfd344679 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Thu, 18 Jun 2009 09:55:17 -0700 Subject: cnic: add NETDEV_1000 and NETDEVICES to Kconfig select NETDEVICES + NETDEV_1000 need to be enabled so that kconfig will check those branches for selects and enforce "select UIO" under CNIC. Otherwise the build fails with: ERROR: "uio_unregister_device" [drivers/net/cnic.ko] undefined! ERROR: "uio_event_notify" [drivers/net/cnic.ko] undefined! ERROR: "__uio_register_device" [drivers/net/cnic.ko] undefined! Signed-off-by: Randy Dunlap Acked-by: Michael Chan Signed-off-by: James Bottomley --- drivers/scsi/bnx2i/Kconfig | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig index b62b482e55e7..1e9f7141102b 100644 --- a/drivers/scsi/bnx2i/Kconfig +++ b/drivers/scsi/bnx2i/Kconfig @@ -1,6 +1,8 @@ config SCSI_BNX2_ISCSI tristate "Broadcom NetXtreme II iSCSI support" select SCSI_ISCSI_ATTRS + select NETDEVICES + select NETDEV_1000 select CNIC depends on PCI ---help--- -- cgit v1.2.3 From ea61fca58c1373a48c0741798f70364d4498d2af Mon Sep 17 00:00:00 2001 From: "Martin K. Petersen" Date: Fri, 15 May 2009 00:40:33 -0400 Subject: scsi_debug: Add support for physical block exponent and alignment This patch adds support for setting the physical block exponent and lowest aligned LBA in the READ CAPACITY(16) response. The B0 VPD page is adjusted accordingly. Signed-off-by: Martin K. Petersen Acked-by: Douglas Gilbert Signed-off-by: James Bottomley --- drivers/scsi/scsi_debug.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 41a21772df12..fb9af207d61d 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -101,6 +101,8 @@ static const char * scsi_debug_version_date = "20070104"; #define DEF_DIF 0 #define DEF_GUARD 0 #define DEF_ATO 1 +#define DEF_PHYSBLK_EXP 0 +#define DEF_LOWEST_ALIGNED 0 /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 @@ -156,6 +158,8 @@ static int scsi_debug_dix = DEF_DIX; static int scsi_debug_dif = DEF_DIF; static int scsi_debug_guard = DEF_GUARD; static int scsi_debug_ato = DEF_ATO; +static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP; +static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; static int scsi_debug_cmnd_count = 0; @@ -657,7 +661,12 @@ static unsigned char vpdb0_data[] = { static int inquiry_evpd_b0(unsigned char * arr) { + unsigned int gran; + memcpy(arr, vpdb0_data, sizeof(vpdb0_data)); + gran = 1 << scsi_debug_physblk_exp; + arr[2] = (gran >> 8) & 0xff; + arr[3] = gran & 0xff; if (sdebug_store_sectors > 0x400) { arr[4] = (sdebug_store_sectors >> 24) & 0xff; arr[5] = (sdebug_store_sectors >> 16) & 0xff; @@ -945,6 +954,9 @@ static int resp_readcap16(struct scsi_cmnd * scp, arr[9] = (scsi_debug_sector_size >> 16) & 0xff; arr[10] = (scsi_debug_sector_size >> 8) & 0xff; arr[11] = scsi_debug_sector_size & 0xff; + arr[13] = scsi_debug_physblk_exp & 0xf; + arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f; + arr[15] = scsi_debug_lowest_aligned & 0xff; if (scsi_debug_dif) { arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */ @@ -2380,6 +2392,8 @@ module_param_named(dix, scsi_debug_dix, int, S_IRUGO); module_param_named(dif, scsi_debug_dif, int, S_IRUGO); module_param_named(guard, scsi_debug_guard, int, S_IRUGO); module_param_named(ato, scsi_debug_ato, int, S_IRUGO); +module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO); +module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO); MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert"); MODULE_DESCRIPTION("SCSI debug adapter driver"); @@ -2401,7 +2415,9 @@ MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])"); MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])"); MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)"); MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)"); -MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)"); +MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)"); +MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)"); +MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)"); MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)"); MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); @@ -2874,6 +2890,18 @@ static int __init scsi_debug_init(void) return -EINVAL; } + if (scsi_debug_physblk_exp > 15) { + printk(KERN_ERR "scsi_debug_init: invalid physblk_exp %u\n", + scsi_debug_physblk_exp); + return -EINVAL; + } + + if (scsi_debug_lowest_aligned > 0x3fff) { + printk(KERN_ERR "scsi_debug_init: lowest_aligned too big: %u\n", + scsi_debug_lowest_aligned); + return -EINVAL; + } + if (scsi_debug_dev_size_mb < 1) scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */ sz = (unsigned long)scsi_debug_dev_size_mb * 1048576; -- cgit v1.2.3 From d5488eb9cd2b06f7dcca7053274edb337987c67c Mon Sep 17 00:00:00 2001 From: Robert Love Date: Wed, 10 Jun 2009 15:30:59 -0700 Subject: fcoe: Add runtime debug logging with module parameter debug_logging This patch converts all FC_DBG statements to use new runtime tunable debug macros. The fcoe.ko module now has a debug_logging module parameter. fcoe_debug_logging is an unsigned integer representing a bitmask of all available logging levels. Currently only two logging levels are supported- bit LSB 0 = general fcoe logging 1 = netdevice related logging This patch also attempts to clean up some debug statement formatting so it's more readable. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe.c | 108 +++++++++++++++++++++++------------------------ drivers/scsi/fcoe/fcoe.h | 24 +++++++++++ 2 files changed, 77 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c index c15878e88157..0a5609bb5817 100644 --- a/drivers/scsi/fcoe/fcoe.c +++ b/drivers/scsi/fcoe/fcoe.c @@ -45,8 +45,6 @@ #include "fcoe.h" -static int debug_fcoe; - MODULE_AUTHOR("Open-FCoE.org"); MODULE_DESCRIPTION("FCoE"); MODULE_LICENSE("GPL v2"); @@ -305,23 +303,22 @@ static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev) #ifdef NETIF_F_FCOE_CRC if (netdev->features & NETIF_F_FCOE_CRC) { lp->crc_offload = 1; - printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n", - netdev->name); + FCOE_NETDEV_DBG(netdev, "Supports FCCRC offload\n"); } #endif #ifdef NETIF_F_FSO if (netdev->features & NETIF_F_FSO) { lp->seq_offload = 1; lp->lso_max = netdev->gso_max_size; - printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n", - netdev->name, lp->lso_max); + FCOE_NETDEV_DBG(netdev, "Supports LSO for max len 0x%x\n", + lp->lso_max); } #endif if (netdev->fcoe_ddp_xid) { lp->lro_enabled = 1; lp->lro_xid = netdev->fcoe_ddp_xid; - printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n", - netdev->name, lp->lro_xid); + FCOE_NETDEV_DBG(netdev, "Supports LRO for max xid 0x%x\n", + lp->lro_xid); } skb_queue_head_init(&fc->fcoe_pending_queue); fc->fcoe_pending_queue_active = 0; @@ -407,7 +404,8 @@ static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, /* add the new host to the SCSI-ml */ rc = scsi_add_host(lp->host, dev); if (rc) { - FC_DBG("fcoe_shost_config:error on scsi_add_host\n"); + FCOE_NETDEV_DBG(fcoe_netdev(lp), "fcoe_shost_config: " + "error on scsi_add_host\n"); return rc; } sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s", @@ -448,8 +446,7 @@ static int fcoe_if_destroy(struct net_device *netdev) BUG_ON(!netdev); - printk(KERN_DEBUG "fcoe_if_destroy:interface on %s\n", - netdev->name); + FCOE_NETDEV_DBG(netdev, "Destroying interface\n"); lp = fcoe_hostlist_lookup(netdev); if (!lp) @@ -560,8 +557,7 @@ static int fcoe_if_create(struct net_device *netdev) BUG_ON(!netdev); - printk(KERN_DEBUG "fcoe_if_create:interface on %s\n", - netdev->name); + FCOE_NETDEV_DBG(netdev, "Create Interface\n"); lp = fcoe_hostlist_lookup(netdev); if (lp) @@ -570,7 +566,7 @@ static int fcoe_if_create(struct net_device *netdev) shost = libfc_host_alloc(&fcoe_shost_template, sizeof(struct fcoe_softc)); if (!shost) { - FC_DBG("Could not allocate host structure\n"); + FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n"); return -ENOMEM; } lp = shost_priv(shost); @@ -579,7 +575,8 @@ static int fcoe_if_create(struct net_device *netdev) /* configure fc_lport, e.g., em */ rc = fcoe_lport_config(lp); if (rc) { - FC_DBG("Could not configure lport\n"); + FCOE_NETDEV_DBG(netdev, "Could not configure lport for the " + "interface\n"); goto out_host_put; } @@ -593,28 +590,32 @@ static int fcoe_if_create(struct net_device *netdev) /* configure lport network properties */ rc = fcoe_netdev_config(lp, netdev); if (rc) { - FC_DBG("Could not configure netdev for the interface\n"); + FCOE_NETDEV_DBG(netdev, "Could not configure netdev for the " + "interface\n"); goto out_netdev_cleanup; } /* configure lport scsi host properties */ rc = fcoe_shost_config(lp, shost, &netdev->dev); if (rc) { - FC_DBG("Could not configure shost for lport\n"); + FCOE_NETDEV_DBG(netdev, "Could not configure shost for the " + "interface\n"); goto out_netdev_cleanup; } /* lport exch manager allocation */ rc = fcoe_em_config(lp); if (rc) { - FC_DBG("Could not configure em for lport\n"); + FCOE_NETDEV_DBG(netdev, "Could not configure the EM for the " + "interface\n"); goto out_netdev_cleanup; } /* Initialize the library */ rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ); if (rc) { - FC_DBG("Could not configure libfc for lport!\n"); + FCOE_NETDEV_DBG(netdev, "Could not configure libfc for the " + "interface\n"); goto out_lp_destroy; } @@ -653,7 +654,7 @@ static int __init fcoe_if_init(void) fc_attach_transport(&fcoe_transport_function); if (!scsi_transport_fcoe_sw) { - printk(KERN_ERR "fcoe_init:fc_attach_transport() failed\n"); + printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n"); return -ENODEV; } @@ -714,7 +715,7 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu) unsigned targ_cpu = smp_processor_id(); #endif /* CONFIG_SMP */ - printk(KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n", cpu); + FCOE_DBG("Destroying receive thread for CPU %d\n", cpu); /* Prevent any new skbs from being queued for this CPU. */ p = &per_cpu(fcoe_percpu, cpu); @@ -736,8 +737,8 @@ static void fcoe_percpu_thread_destroy(unsigned int cpu) p0 = &per_cpu(fcoe_percpu, targ_cpu); spin_lock_bh(&p0->fcoe_rx_list.lock); if (p0->thread) { - FC_DBG("Moving frames from CPU %d to CPU %d\n", - cpu, targ_cpu); + FCOE_DBG("Moving frames from CPU %d to CPU %d\n", + cpu, targ_cpu); while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL) __skb_queue_tail(&p0->fcoe_rx_list, skb); @@ -803,12 +804,12 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - FC_DBG("CPU %x online: Create Rx thread\n", cpu); + FCOE_DBG("CPU %x online: Create Rx thread\n", cpu); fcoe_percpu_thread_create(cpu); break; case CPU_DEAD: case CPU_DEAD_FROZEN: - FC_DBG("CPU %x offline: Remove Rx thread\n", cpu); + FCOE_DBG("CPU %x offline: Remove Rx thread\n", cpu); fcoe_percpu_thread_destroy(cpu); break; default: @@ -846,24 +847,21 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type); lp = fc->ctlr.lp; if (unlikely(lp == NULL)) { - FC_DBG("cannot find hba structure"); + FCOE_NETDEV_DBG(dev, "Cannot find hba structure"); goto err2; } if (!lp->link_up) goto err2; - if (unlikely(debug_fcoe)) { - FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p " - "end:%p sum:%d dev:%s", skb->len, skb->data_len, - skb->head, skb->data, skb_tail_pointer(skb), - skb_end_pointer(skb), skb->csum, - skb->dev ? skb->dev->name : ""); - - } + FCOE_NETDEV_DBG(dev, "skb_info: len:%d data_len:%d head:%p " + "data:%p tail:%p end:%p sum:%d dev:%s", + skb->len, skb->data_len, skb->head, skb->data, + skb_tail_pointer(skb), skb_end_pointer(skb), + skb->csum, skb->dev ? skb->dev->name : ""); /* check for FCOE packet type */ if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) { - FC_DBG("wrong FC type frame"); + FCOE_NETDEV_DBG(dev, "Wrong FC type frame"); goto err; } @@ -901,8 +899,9 @@ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, * the first CPU now. For non-SMP systems this * will check the same CPU twice. */ - FC_DBG("CPU is online, but no receive thread ready " - "for incoming skb- using first online CPU.\n"); + FCOE_NETDEV_DBG(dev, "CPU is online, but no receive thread " + "ready for incoming skb- using first online " + "CPU.\n"); spin_unlock_bh(&fps->fcoe_rx_list.lock); cpu = first_cpu(cpu_online_map); @@ -1201,19 +1200,17 @@ int fcoe_percpu_receive_thread(void *arg) fr = fcoe_dev_from_skb(skb); lp = fr->fr_dev; if (unlikely(lp == NULL)) { - FC_DBG("invalid HBA Structure"); + FCOE_NETDEV_DBG(skb->dev, "Invalid HBA Structure"); kfree_skb(skb); continue; } - if (unlikely(debug_fcoe)) { - FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p " - "tail:%p end:%p sum:%d dev:%s", - skb->len, skb->data_len, - skb->head, skb->data, skb_tail_pointer(skb), - skb_end_pointer(skb), skb->csum, - skb->dev ? skb->dev->name : ""); - } + FCOE_NETDEV_DBG(skb->dev, "skb_info: len:%d data_len:%d " + "head:%p data:%p tail:%p end:%p sum:%d dev:%s", + skb->len, skb->data_len, + skb->head, skb->data, skb_tail_pointer(skb), + skb_end_pointer(skb), skb->csum, + skb->dev ? skb->dev->name : ""); /* * Save source MAC address before discarding header. @@ -1233,7 +1230,7 @@ int fcoe_percpu_receive_thread(void *arg) stats = fc_lport_get_stats(lp); if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) { if (stats->ErrorFrames < 5) - printk(KERN_WARNING "FCoE version " + printk(KERN_WARNING "fcoe: FCoE version " "mismatch: The frame has " "version %x, but the " "initiator supports version " @@ -1286,7 +1283,7 @@ int fcoe_percpu_receive_thread(void *arg) if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) { if (le32_to_cpu(fr_crc(fp)) != ~crc32(~0, skb->data, fr_len)) { - if (debug_fcoe || stats->InvalidCRCCount < 5) + if (stats->InvalidCRCCount < 5) printk(KERN_WARNING "fcoe: dropping " "frame with CRC error\n"); stats->InvalidCRCCount++; @@ -1432,7 +1429,8 @@ static int fcoe_device_notification(struct notifier_block *notifier, case NETDEV_REGISTER: break; default: - FC_DBG("Unknown event %ld from netdev netlink\n", event); + FCOE_NETDEV_DBG(real_dev, "Unknown event %ld " + "from netdev netlink\n", event); } if (link_possible && !fcoe_link_ok(lp)) fcoe_ctlr_link_up(&fc->ctlr); @@ -1505,8 +1503,8 @@ static int fcoe_ethdrv_get(const struct net_device *netdev) owner = fcoe_netdev_to_module_owner(netdev); if (owner) { - printk(KERN_DEBUG "fcoe:hold driver module %s for %s\n", - module_name(owner), netdev->name); + FCOE_NETDEV_DBG(netdev, "Hold driver module %s\n", + module_name(owner)); return try_module_get(owner); } return -ENODEV; @@ -1527,8 +1525,8 @@ static int fcoe_ethdrv_put(const struct net_device *netdev) owner = fcoe_netdev_to_module_owner(netdev); if (owner) { - printk(KERN_DEBUG "fcoe:release driver module %s for %s\n", - module_name(owner), netdev->name); + FCOE_NETDEV_DBG(netdev, "Release driver module %s\n", + module_name(owner)); module_put(owner); return 0; } @@ -1559,7 +1557,7 @@ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) } rc = fcoe_if_destroy(netdev); if (rc) { - printk(KERN_ERR "fcoe: fcoe_if_destroy(%s) failed\n", + printk(KERN_ERR "fcoe: Failed to destroy interface (%s)\n", netdev->name); rc = -EIO; goto out_putdev; @@ -1598,7 +1596,7 @@ static int fcoe_create(const char *buffer, struct kernel_param *kp) rc = fcoe_if_create(netdev); if (rc) { - printk(KERN_ERR "fcoe: fcoe_if_create(%s) failed\n", + printk(KERN_ERR "fcoe: Failed to create interface (%s)\n", netdev->name); fcoe_ethdrv_put(netdev); rc = -EIO; diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h index a1eb8c1988b0..0d724fa0898f 100644 --- a/drivers/scsi/fcoe/fcoe.h +++ b/drivers/scsi/fcoe/fcoe.h @@ -40,6 +40,30 @@ #define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */ #define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */ +unsigned int fcoe_debug_logging; +module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); + +#define FCOE_LOGGING 0x01 /* General logging, not categorized */ +#define FCOE_NETDEV_LOGGING 0x02 /* Netdevice logging */ + +#define FCOE_CHECK_LOGGING(LEVEL, CMD) \ +do { \ + if (unlikely(fcoe_debug_logging & LEVEL)) \ + do { \ + CMD; \ + } while (0); \ +} while (0); + +#define FCOE_DBG(fmt, args...) \ + FCOE_CHECK_LOGGING(FCOE_LOGGING, \ + printk(KERN_INFO "fcoe: " fmt, ##args);) + +#define FCOE_NETDEV_DBG(netdev, fmt, args...) \ + FCOE_CHECK_LOGGING(FCOE_NETDEV_LOGGING, \ + printk(KERN_INFO "fcoe: %s" fmt, \ + netdev->name, ##args);) + /* * this percpu struct for fcoe */ -- cgit v1.2.3 From 650bd12b9e31ec51d7ad0df3c4f94d863b827976 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Wed, 10 Jun 2009 15:31:05 -0700 Subject: libfcoe: Add runtime debugging with module param debug_logging This patch adds a 'debug_logging' module parameter to libfcoe.ko. It is an unsigned int that represents a bitmask of available debug logging levels, each of which can be tuned at runtime. Currently there are only two logging levels for this module- bit LSB 0 = libfcoe general logging 1 = FIP logging Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 94 ++++++++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 2f5bc7fd3fa9..f544340d318b 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -56,15 +56,28 @@ static void fcoe_ctlr_recv_work(struct work_struct *); static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS; -static u32 fcoe_ctlr_debug; /* 1 for basic, 2 for noisy debug */ +unsigned int libfcoe_debug_logging; +module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); -#define FIP_DBG_LVL(level, fmt, args...) \ +#define LIBFCOE_LOGGING 0x01 /* General logging, not categorized */ +#define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */ + +#define LIBFCOE_CHECK_LOGGING(LEVEL, CMD) \ +do { \ + if (unlikely(libfcoe_debug_logging & LEVEL)) \ do { \ - if (fcoe_ctlr_debug >= (level)) \ - FC_DBG(fmt, ##args); \ - } while (0) + CMD; \ + } while (0); \ +} while (0); + +#define LIBFCOE_DBG(fmt, args...) \ + LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING, \ + printk(KERN_INFO "libfcoe: " fmt, ##args);) -#define FIP_DBG(fmt, args...) FIP_DBG_LVL(1, fmt, ##args) +#define LIBFCOE_FIP_DBG(fmt, args...) \ + LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING, \ + printk(KERN_INFO "fip: " fmt, ##args);) /* * Return non-zero if FCF fcoe_size has been validated. @@ -243,7 +256,7 @@ void fcoe_ctlr_link_up(struct fcoe_ctlr *fip) fip->last_link = 1; fip->link = 1; spin_unlock_bh(&fip->lock); - FIP_DBG("%s", "setting AUTO mode.\n"); + LIBFCOE_FIP_DBG("%s", "setting AUTO mode.\n"); fc_linkup(fip->lp); fcoe_ctlr_solicit(fip, NULL); } else @@ -614,7 +627,8 @@ static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf) ((struct fip_mac_desc *)desc)->fd_mac, ETH_ALEN); if (!is_valid_ether_addr(fcf->fcf_mac)) { - FIP_DBG("invalid MAC addr in FIP adv\n"); + LIBFCOE_FIP_DBG("Invalid MAC address " + "in FIP adv\n"); return -EINVAL; } break; @@ -647,8 +661,8 @@ static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf) case FIP_DT_LOGO: case FIP_DT_ELP: default: - FIP_DBG("unexpected descriptor type %x in FIP adv\n", - desc->fip_dtype); + LIBFCOE_FIP_DBG("unexpected descriptor type %x " + "in FIP adv\n", desc->fip_dtype); /* standard says ignore unknown descriptors >= 128 */ if (desc->fip_dtype < FIP_DT_VENDOR_BASE) return -EINVAL; @@ -664,8 +678,8 @@ static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf) return 0; len_err: - FIP_DBG("FIP length error in descriptor type %x len %zu\n", - desc->fip_dtype, dlen); + LIBFCOE_FIP_DBG("FIP length error in descriptor type %x len %zu\n", + desc->fip_dtype, dlen); return -EINVAL; } @@ -728,9 +742,10 @@ static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb) } mtu_valid = fcoe_ctlr_mtu_valid(fcf); fcf->time = jiffies; - FIP_DBG_LVL(found ? 2 : 1, "%s FCF for fab %llx map %x val %d\n", - found ? "old" : "new", - fcf->fabric_name, fcf->fc_map, mtu_valid); + if (!found) { + LIBFCOE_FIP_DBG("New FCF for fab %llx map %x val %d\n", + fcf->fabric_name, fcf->fc_map, mtu_valid); + } /* * If this advertisement is not solicited and our max receive size @@ -807,7 +822,8 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) ((struct fip_mac_desc *)desc)->fd_mac, ETH_ALEN); if (!is_valid_ether_addr(granted_mac)) { - FIP_DBG("invalid MAC addrs in FIP ELS\n"); + LIBFCOE_FIP_DBG("Invalid MAC address " + "in FIP ELS\n"); goto drop; } break; @@ -825,8 +841,8 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) els_dtype = desc->fip_dtype; break; default: - FIP_DBG("unexpected descriptor type %x " - "in FIP adv\n", desc->fip_dtype); + LIBFCOE_FIP_DBG("unexpected descriptor type %x " + "in FIP adv\n", desc->fip_dtype); /* standard says ignore unknown descriptors >= 128 */ if (desc->fip_dtype < FIP_DT_VENDOR_BASE) goto drop; @@ -867,8 +883,8 @@ static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb) return; len_err: - FIP_DBG("FIP length error in descriptor type %x len %zu\n", - desc->fip_dtype, dlen); + LIBFCOE_FIP_DBG("FIP length error in descriptor type %x len %zu\n", + desc->fip_dtype, dlen); drop: kfree_skb(skb); } @@ -894,7 +910,7 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, struct fc_lport *lp = fip->lp; u32 desc_mask; - FIP_DBG("Clear Virtual Link received\n"); + LIBFCOE_FIP_DBG("Clear Virtual Link received\n"); if (!fcf) return; if (!fcf || !fc_host_port_id(lp->host)) @@ -952,9 +968,9 @@ static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip, * reset only if all required descriptors were present and valid. */ if (desc_mask) { - FIP_DBG("missing descriptors mask %x\n", desc_mask); + LIBFCOE_FIP_DBG("missing descriptors mask %x\n", desc_mask); } else { - FIP_DBG("performing Clear Virtual Link\n"); + LIBFCOE_FIP_DBG("performing Clear Virtual Link\n"); fcoe_ctlr_reset(fip, FIP_ST_ENABLED); } } @@ -1002,10 +1018,6 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) op = ntohs(fiph->fip_op); sub = fiph->fip_subcode; - FIP_DBG_LVL(2, "ver %x op %x/%x dl %x fl %x\n", - FIP_VER_DECAPS(fiph->fip_ver), op, sub, - ntohs(fiph->fip_dl_len), ntohs(fiph->fip_flags)); - if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER) goto drop; if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len) @@ -1017,7 +1029,7 @@ static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb) fip->map_dest = 0; fip->state = FIP_ST_ENABLED; state = FIP_ST_ENABLED; - FIP_DBG("using FIP mode\n"); + LIBFCOE_FIP_DBG("Using FIP mode\n"); } spin_unlock_bh(&fip->lock); if (state != FIP_ST_ENABLED) @@ -1052,14 +1064,15 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) struct fcoe_fcf *best = NULL; list_for_each_entry(fcf, &fip->fcfs, list) { - FIP_DBG("consider FCF for fab %llx VFID %d map %x val %d\n", - fcf->fabric_name, fcf->vfid, - fcf->fc_map, fcoe_ctlr_mtu_valid(fcf)); + LIBFCOE_FIP_DBG("consider FCF for fab %llx VFID %d map %x " + "val %d\n", fcf->fabric_name, fcf->vfid, + fcf->fc_map, fcoe_ctlr_mtu_valid(fcf)); if (!fcoe_ctlr_fcf_usable(fcf)) { - FIP_DBG("FCF for fab %llx map %x %svalid %savailable\n", - fcf->fabric_name, fcf->fc_map, - (fcf->flags & FIP_FL_SOL) ? "" : "in", - (fcf->flags & FIP_FL_AVAIL) ? "" : "un"); + LIBFCOE_FIP_DBG("FCF for fab %llx map %x %svalid " + "%savailable\n", fcf->fabric_name, + fcf->fc_map, (fcf->flags & FIP_FL_SOL) + ? "" : "in", (fcf->flags & FIP_FL_AVAIL) + ? "" : "un"); continue; } if (!best) { @@ -1069,7 +1082,8 @@ static void fcoe_ctlr_select(struct fcoe_ctlr *fip) if (fcf->fabric_name != best->fabric_name || fcf->vfid != best->vfid || fcf->fc_map != best->fc_map) { - FIP_DBG("conflicting fabric, VFID, or FC-MAP\n"); + LIBFCOE_FIP_DBG("Conflicting fabric, VFID, " + "or FC-MAP\n"); return; } if (fcf->pri < best->pri) @@ -1113,7 +1127,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) if (sel != fcf) { fcf = sel; /* the old FCF may have been freed */ if (sel) { - printk(KERN_INFO "host%d: FIP selected " + printk(KERN_INFO "libfcoe: host%d: FIP selected " "Fibre-Channel Forwarder MAC %s\n", fip->lp->host->host_no, print_mac(buf, sel->fcf_mac)); @@ -1123,7 +1137,7 @@ static void fcoe_ctlr_timeout(unsigned long arg) fip->ctlr_ka_time = jiffies + sel->fka_period; fip->link = 1; } else { - printk(KERN_NOTICE "host%d: " + printk(KERN_NOTICE "libfcoe: host%d: " "FIP Fibre-Channel Forwarder timed out. " "Starting FCF discovery.\n", fip->lp->host->host_no); @@ -1247,7 +1261,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) return -EINVAL; } fip->state = FIP_ST_NON_FIP; - FIP_DBG("received FLOGI LS_ACC using non-FIP mode\n"); + LIBFCOE_FIP_DBG("received FLOGI LS_ACC using non-FIP mode\n"); /* * FLOGI accepted. @@ -1276,7 +1290,7 @@ int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa) memcpy(fip->dest_addr, sa, ETH_ALEN); fip->map_dest = 0; if (fip->state == FIP_ST_NON_FIP) - FIP_DBG("received FLOGI REQ, " + LIBFCOE_FIP_DBG("received FLOGI REQ, " "using non-FIP mode\n"); fip->state = FIP_ST_NON_FIP; } -- cgit v1.2.3 From 7414705ea4aef9ce438e547f3138a680d2d1096c Mon Sep 17 00:00:00 2001 From: Robert Love Date: Wed, 10 Jun 2009 15:31:10 -0700 Subject: libfc: Add runtime debugging with debug_logging module parameter This patch adds the /sys/module/libfc/parameters/debug_logging file to sysfs as a module parameter. It accepts an integer bitmask for logging. Currently it supports: bit LSB 0 = general libfc debugging 1 = lport debugging 2 = disc debugging 3 = rport debugging 4 = fcp debugging 5 = EM debugging 6 = exch/seq debugging 7 = scsi logging (mostly error handling) the other bits are not used at this time. The patch converts all of the libfc source files to use these new macros and removes the old FC_DBG macro. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 83 ++++++++++------------ drivers/scsi/libfc/fc_exch.c | 58 +++++++--------- drivers/scsi/libfc/fc_fcp.c | 97 +++++++++++++------------- drivers/scsi/libfc/fc_lport.c | 156 ++++++++++++++++++++---------------------- drivers/scsi/libfc/fc_rport.c | 120 ++++++++++++++------------------ include/scsi/fc_encode.h | 2 - include/scsi/libfc.h | 77 ++++++++++++++++++--- 7 files changed, 301 insertions(+), 292 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 4c880656990b..6fabf66972b9 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -45,14 +45,6 @@ #define FC_DISC_DELAY 3 -static int fc_disc_debug; - -#define FC_DEBUG_DISC(fmt...) \ - do { \ - if (fc_disc_debug) \ - FC_DBG(fmt); \ - } while (0) - static void fc_disc_gpn_ft_req(struct fc_disc *); static void fc_disc_gpn_ft_resp(struct fc_seq *, struct fc_frame *, void *); static int fc_disc_new_target(struct fc_disc *, struct fc_rport *, @@ -137,8 +129,8 @@ static void fc_disc_rport_callback(struct fc_lport *lport, struct fc_rport_libfc_priv *rdata = rport->dd_data; struct fc_disc *disc = &lport->disc; - FC_DEBUG_DISC("Received a %d event for port (%6x)\n", event, - rport->port_id); + FC_DISC_DBG(disc, "Received a %d event for port (%6x)\n", event, + rport->port_id); switch (event) { case RPORT_EV_CREATED: @@ -191,8 +183,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, lport = disc->lport; - FC_DEBUG_DISC("Received an RSCN event on port (%6x)\n", - fc_host_port_id(lport->host)); + FC_DISC_DBG(disc, "Received an RSCN event\n"); /* make sure the frame contains an RSCN message */ rp = fc_frame_payload_get(fp, sizeof(*rp)); @@ -225,8 +216,8 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, */ switch (fmt) { case ELS_ADDR_FMT_PORT: - FC_DEBUG_DISC("Port address format for port (%6x)\n", - ntoh24(pp->rscn_fid)); + FC_DISC_DBG(disc, "Port address format for port " + "(%6x)\n", ntoh24(pp->rscn_fid)); dp = kzalloc(sizeof(*dp), GFP_KERNEL); if (!dp) { redisc = 1; @@ -243,19 +234,19 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, case ELS_ADDR_FMT_DOM: case ELS_ADDR_FMT_FAB: default: - FC_DEBUG_DISC("Address format is (%d)\n", fmt); + FC_DISC_DBG(disc, "Address format is (%d)\n", fmt); redisc = 1; break; } } lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); if (redisc) { - FC_DEBUG_DISC("RSCN received: rediscovering\n"); + FC_DISC_DBG(disc, "RSCN received: rediscovering\n"); fc_disc_restart(disc); } else { - FC_DEBUG_DISC("RSCN received: not rediscovering. " - "redisc %d state %d in_prog %d\n", - redisc, lport->state, disc->pending); + FC_DISC_DBG(disc, "RSCN received: not rediscovering. " + "redisc %d state %d in_prog %d\n", + redisc, lport->state, disc->pending); list_for_each_entry_safe(dp, next, &disc_ports, peers) { list_del(&dp->peers); rport = lport->tt.rport_lookup(lport, dp->ids.port_id); @@ -270,7 +261,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, fc_frame_free(fp); return; reject: - FC_DEBUG_DISC("Received a bad RSCN frame\n"); + FC_DISC_DBG(disc, "Received a bad RSCN frame\n"); rjt_data.fp = NULL; rjt_data.reason = ELS_RJT_LOGIC; rjt_data.explan = ELS_EXPL_NONE; @@ -302,7 +293,8 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, mutex_unlock(&disc->disc_mutex); break; default: - FC_DBG("Received an unsupported request. opcode (%x)\n", op); + FC_DISC_DBG(disc, "Received an unsupported request, " + "the opcode is (%x)\n", op); break; } } @@ -320,12 +312,10 @@ static void fc_disc_restart(struct fc_disc *disc) struct fc_rport_libfc_priv *rdata, *next; struct fc_lport *lport = disc->lport; - FC_DEBUG_DISC("Restarting discovery for port (%6x)\n", - fc_host_port_id(lport->host)); + FC_DISC_DBG(disc, "Restarting discovery\n"); list_for_each_entry_safe(rdata, next, &disc->rports, peers) { rport = PRIV_TO_RPORT(rdata); - FC_DEBUG_DISC("list_del(%6x)\n", rport->port_id); list_del(&rdata->peers); lport->tt.rport_logoff(rport); } @@ -485,8 +475,7 @@ static void fc_disc_done(struct fc_disc *disc) struct fc_lport *lport = disc->lport; enum fc_disc_event event; - FC_DEBUG_DISC("Discovery complete for port (%6x)\n", - fc_host_port_id(lport->host)); + FC_DISC_DBG(disc, "Discovery complete\n"); event = disc->event; disc->event = DISC_EV_NONE; @@ -510,10 +499,10 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) { struct fc_lport *lport = disc->lport; unsigned long delay = 0; - if (fc_disc_debug) - FC_DBG("Error %ld, retries %d/%d\n", - PTR_ERR(fp), disc->retry_count, - FC_DISC_RETRY_LIMIT); + + FC_DISC_DBG(disc, "Error %ld, retries %d/%d\n", + PTR_ERR(fp), disc->retry_count, + FC_DISC_RETRY_LIMIT); if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) { /* @@ -649,9 +638,9 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) &disc->rogue_rports); lport->tt.rport_login(rport); } else - FC_DBG("Failed to allocate memory for " - "the newly discovered port (%6x)\n", - dp.ids.port_id); + printk(KERN_WARNING "libfc: Failed to allocate " + "memory for the newly discovered port " + "(%6x)\n", dp.ids.port_id); } if (np->fp_flags & FC_NS_FID_LAST) { @@ -671,9 +660,8 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) */ if (error == 0 && len > 0 && len < sizeof(*np)) { if (np != &disc->partial_buf) { - FC_DEBUG_DISC("Partial buffer remains " - "for discovery by (%6x)\n", - fc_host_port_id(lport->host)); + FC_DISC_DBG(disc, "Partial buffer remains " + "for discovery\n"); memcpy(&disc->partial_buf, np, len); } disc->buf_len = (unsigned char) len; @@ -721,8 +709,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, int error; mutex_lock(&disc->disc_mutex); - FC_DEBUG_DISC("Received a GPN_FT response on port (%6x)\n", - fc_host_port_id(disc->lport->host)); + FC_DISC_DBG(disc, "Received a GPN_FT response\n"); if (IS_ERR(fp)) { fc_disc_error(disc, fp); @@ -738,30 +725,30 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, disc->seq_count == 0) { cp = fc_frame_payload_get(fp, sizeof(*cp)); if (!cp) { - FC_DBG("GPN_FT response too short, len %d\n", - fr_len(fp)); + FC_DISC_DBG(disc, "GPN_FT response too short, len %d\n", + fr_len(fp)); } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) { /* Accepted, parse the response. */ buf = cp + 1; len -= sizeof(*cp); } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { - FC_DBG("GPN_FT rejected reason %x exp %x " - "(check zoning)\n", cp->ct_reason, - cp->ct_explan); + FC_DISC_DBG(disc, "GPN_FT rejected reason %x exp %x " + "(check zoning)\n", cp->ct_reason, + cp->ct_explan); disc->event = DISC_EV_FAILED; fc_disc_done(disc); } else { - FC_DBG("GPN_FT unexpected response code %x\n", - ntohs(cp->ct_cmd)); + FC_DISC_DBG(disc, "GPN_FT unexpected response code " + "%x\n", ntohs(cp->ct_cmd)); } } else if (fr_sof(fp) == FC_SOF_N3 && seq_cnt == disc->seq_count) { buf = fh + 1; } else { - FC_DBG("GPN_FT unexpected frame - out of sequence? " - "seq_cnt %x expected %x sof %x eof %x\n", - seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp)); + FC_DISC_DBG(disc, "GPN_FT unexpected frame - out of sequence? " + "seq_cnt %x expected %x sof %x eof %x\n", + seq_cnt, disc->seq_count, fr_sof(fp), fr_eof(fp)); } if (buf) { error = fc_disc_gpn_ft_parse(disc, buf, len); diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 7af9bceb8aa9..2bc22be5f849 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -32,18 +32,7 @@ #include #include -/* - * fc_exch_debug can be set in debugger or at compile time to get more logs. - */ -static int fc_exch_debug; - -#define FC_DEBUG_EXCH(fmt...) \ - do { \ - if (fc_exch_debug) \ - FC_DBG(fmt); \ - } while (0) - -static struct kmem_cache *fc_em_cachep; /* cache for exchanges */ +static struct kmem_cache *fc_em_cachep; /* cache for exchanges */ /* * Structure and function definitions for managing Fibre Channel Exchanges @@ -333,8 +322,8 @@ static inline void fc_exch_timer_set_locked(struct fc_exch *ep, if (ep->state & (FC_EX_RST_CLEANUP | FC_EX_DONE)) return; - FC_DEBUG_EXCH("Exchange (%4x) timed out, notifying the upper layer\n", - ep->xid); + FC_EXCH_DBG(ep, "Exchange timed out, notifying the upper layer\n"); + if (schedule_delayed_work(&ep->timeout_work, msecs_to_jiffies(timer_msec))) fc_exch_hold(ep); /* hold for timer */ @@ -545,7 +534,7 @@ struct fc_exch *fc_exch_alloc(struct fc_exch_mgr *mp, /* alloc a new xid */ xid = fc_em_alloc_xid(mp, fp); if (!xid) { - printk(KERN_ERR "fc_em_alloc_xid() failed\n"); + printk(KERN_WARNING "libfc: Failed to allocate an exhange\n"); goto err; } } @@ -820,8 +809,8 @@ static struct fc_seq *fc_seq_start_next_locked(struct fc_seq *sp) struct fc_exch *ep = fc_seq_exch(sp); sp = fc_seq_alloc(ep, ep->seq_id++); - FC_DEBUG_EXCH("exch %4x f_ctl %6x seq %2x\n", - ep->xid, ep->f_ctl, sp->id); + FC_EXCH_DBG(ep, "f_ctl %6x seq %2x\n", + ep->f_ctl, sp->id); return sp; } /* @@ -901,7 +890,7 @@ void fc_seq_els_rsp_send(struct fc_seq *sp, enum fc_els_cmd els_cmd, fc_exch_els_rec(sp, els_data->fp); break; default: - FC_DBG("Invalid ELS CMD:%x\n", els_cmd); + FC_EXCH_DBG(fc_seq_exch(sp), "Invalid ELS CMD:%x\n", els_cmd); } } EXPORT_SYMBOL(fc_seq_els_rsp_send); @@ -1134,7 +1123,7 @@ static void fc_exch_recv_req(struct fc_lport *lp, struct fc_exch_mgr *mp, lp->tt.lport_recv(lp, sp, fp); fc_exch_release(ep); /* release from lookup */ } else { - FC_DEBUG_EXCH("exch/seq lookup failed: reject %x\n", reject); + FC_EM_DBG(mp, "exch/seq lookup failed: reject %x\n", reject); fc_frame_free(fp); } } @@ -1242,10 +1231,10 @@ static void fc_exch_recv_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) sp = fc_seq_lookup_orig(mp, fp); /* doesn't hold sequence */ if (!sp) { atomic_inc(&mp->stats.xid_not_found); - FC_DEBUG_EXCH("seq lookup failed\n"); + FC_EM_DBG(mp, "seq lookup failed\n"); } else { atomic_inc(&mp->stats.non_bls_resp); - FC_DEBUG_EXCH("non-BLS response to sequence"); + FC_EM_DBG(mp, "non-BLS response to sequence"); } fc_frame_free(fp); } @@ -1266,8 +1255,8 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp) int rc = 1, has_rec = 0; fh = fc_frame_header_get(fp); - FC_DEBUG_EXCH("exch: BLS rctl %x - %s\n", - fh->fh_r_ctl, fc_exch_rctl_name(fh->fh_r_ctl)); + FC_EXCH_DBG(ep, "exch: BLS rctl %x - %s\n", fh->fh_r_ctl, + fc_exch_rctl_name(fh->fh_r_ctl)); if (cancel_delayed_work_sync(&ep->timeout_work)) fc_exch_release(ep); /* release from pending timer hold */ @@ -1359,9 +1348,9 @@ static void fc_exch_recv_bls(struct fc_exch_mgr *mp, struct fc_frame *fp) case FC_RCTL_ACK_0: break; default: - FC_DEBUG_EXCH("BLS rctl %x - %s received", - fh->fh_r_ctl, - fc_exch_rctl_name(fh->fh_r_ctl)); + FC_EXCH_DBG(ep, "BLS rctl %x - %s received", + fh->fh_r_ctl, + fc_exch_rctl_name(fh->fh_r_ctl)); break; } fc_frame_free(fp); @@ -1599,7 +1588,8 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg) if (err == -FC_EX_CLOSED || err == -FC_EX_TIMEOUT) goto cleanup; - FC_DBG("Cannot process RRQ, because of frame error %d\n", err); + FC_EXCH_DBG(aborted_ep, "Cannot process RRQ, " + "frame error %d\n", err); return; } @@ -1608,12 +1598,13 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg) switch (op) { case ELS_LS_RJT: - FC_DBG("LS_RJT for RRQ"); + FC_EXCH_DBG(aborted_ep, "LS_RJT for RRQ"); /* fall through */ case ELS_LS_ACC: goto cleanup; default: - FC_DBG("unexpected response op %x for RRQ", op); + FC_EXCH_DBG(aborted_ep, "unexpected response op %x " + "for RRQ", op); return; } @@ -1740,8 +1731,8 @@ struct fc_exch_mgr *fc_exch_mgr_alloc(struct fc_lport *lp, size_t len; if (max_xid <= min_xid || min_xid == 0 || max_xid == FC_XID_UNKNOWN) { - FC_DBG("Invalid min_xid 0x:%x and max_xid 0x:%x\n", - min_xid, max_xid); + FC_LPORT_DBG(lp, "Invalid min_xid 0x:%x and max_xid 0x:%x\n", + min_xid, max_xid); return NULL; } @@ -1878,7 +1869,8 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp, /* lport lock ? */ if (!lp || !mp || (lp->state == LPORT_ST_NONE)) { - FC_DBG("fc_lport or EM is not allocated and configured"); + FC_LPORT_DBG(lp, "Receiving frames for an lport that " + "has not been initialized correctly\n"); fc_frame_free(fp); return; } @@ -1904,7 +1896,7 @@ void fc_exch_recv(struct fc_lport *lp, struct fc_exch_mgr *mp, fc_exch_recv_req(lp, mp, fp); break; default: - FC_DBG("dropping invalid frame (eof %x)", fr_eof(fp)); + FC_EM_DBG(mp, "dropping invalid frame (eof %x)", fr_eof(fp)); fc_frame_free(fp); break; } diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index ad8b747837b0..e303e0d12c4b 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -43,13 +43,9 @@ MODULE_AUTHOR("Open-FCoE.org"); MODULE_DESCRIPTION("libfc"); MODULE_LICENSE("GPL v2"); -static int fc_fcp_debug; - -#define FC_DEBUG_FCP(fmt...) \ - do { \ - if (fc_fcp_debug) \ - FC_DBG(fmt); \ - } while (0) +unsigned int fc_debug_logging; +module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels"); static struct kmem_cache *scsi_pkt_cachep; @@ -347,8 +343,8 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && fc_frame_crc_check(fp)) goto crc_err; - FC_DEBUG_FCP("data received past end. len %zx offset %zx " - "data_len %x\n", len, offset, fsp->data_len); + FC_FCP_DBG(fsp, "data received past end. len %zx offset %zx " + "data_len %x\n", len, offset, fsp->data_len); fc_fcp_retry_cmd(fsp); return; } @@ -411,7 +407,8 @@ crc_err: stats->ErrorFrames++; /* FIXME - per cpu count, not total count! */ if (stats->InvalidCRCCount++ < 5) - printk(KERN_WARNING "CRC error on data frame for port (%6x)\n", + printk(KERN_WARNING "libfc: CRC error on data " + "frame for port (%6x)\n", fc_host_port_id(lp->host)); /* * Assume the frame is total garbage. @@ -475,14 +472,14 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, WARN_ON(seq_blen <= 0); if (unlikely(offset + seq_blen > fsp->data_len)) { /* this should never happen */ - FC_DEBUG_FCP("xfer-ready past end. seq_blen %zx offset %zx\n", - seq_blen, offset); + FC_FCP_DBG(fsp, "xfer-ready past end. seq_blen %zx " + "offset %zx\n", seq_blen, offset); fc_fcp_send_abort(fsp); return 0; } else if (offset != fsp->xfer_len) { /* Out of Order Data Request - no problem, but unexpected. */ - FC_DEBUG_FCP("xfer-ready non-contiguous. " - "seq_blen %zx offset %zx\n", seq_blen, offset); + FC_FCP_DBG(fsp, "xfer-ready non-contiguous. " + "seq_blen %zx offset %zx\n", seq_blen, offset); } /* @@ -493,7 +490,7 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq, t_blen = fsp->max_payload; if (lp->seq_offload) { t_blen = min(seq_blen, (size_t)lp->lso_max); - FC_DEBUG_FCP("fsp=%p:lso:blen=%zx lso_max=0x%x t_blen=%zx\n", + FC_FCP_DBG(fsp, "fsp=%p:lso:blen=%zx lso_max=0x%x t_blen=%zx\n", fsp, seq_blen, lp->lso_max, t_blen); } @@ -694,7 +691,7 @@ static void fc_fcp_reduce_can_queue(struct fc_lport *lp) if (!can_queue) can_queue = 1; lp->host->can_queue = can_queue; - shost_printk(KERN_ERR, lp->host, "Could not allocate frame.\n" + shost_printk(KERN_ERR, lp->host, "libfc: Could not allocate frame.\n" "Reducing can_queue to %d.\n", can_queue); done: spin_unlock_irqrestore(lp->host->host_lock, flags); @@ -768,7 +765,7 @@ static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg) fc_fcp_resp(fsp, fp); } else { - FC_DBG("unexpected frame. r_ctl %x\n", r_ctl); + FC_FCP_DBG(fsp, "unexpected frame. r_ctl %x\n", r_ctl); } unlock: fc_fcp_unlock_pkt(fsp); @@ -877,17 +874,17 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) return; } fsp->status_code = FC_DATA_OVRRUN; - FC_DBG("tgt %6x xfer len %zx greater than expected len %x. " - "data len %x\n", - fsp->rport->port_id, - fsp->xfer_len, expected_len, fsp->data_len); + FC_FCP_DBG(fsp, "tgt %6x xfer len %zx greater than expected, " + "len %x, data len %x\n", + fsp->rport->port_id, + fsp->xfer_len, expected_len, fsp->data_len); } fc_fcp_complete_locked(fsp); return; len_err: - FC_DBG("short FCP response. flags 0x%x len %u respl %u snsl %u\n", - flags, fr_len(fp), respl, snsl); + FC_FCP_DBG(fsp, "short FCP response. flags 0x%x len %u respl %u " + "snsl %u\n", flags, fr_len(fp), respl, snsl); err: fsp->status_code = FC_ERROR; fc_fcp_complete_locked(fsp); @@ -1107,13 +1104,11 @@ static void fc_fcp_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) if (fc_fcp_lock_pkt(fsp)) return; - switch (error) { - case -FC_EX_CLOSED: + if (error == -FC_EX_CLOSED) { fc_fcp_retry_cmd(fsp); goto unlock; - default: - FC_DBG("unknown error %ld\n", PTR_ERR(fp)); } + /* * clear abort pending, because the lower layer * decided to force completion. @@ -1145,10 +1140,10 @@ static int fc_fcp_pkt_abort(struct fc_lport *lp, struct fc_fcp_pkt *fsp) fsp->wait_for_comp = 0; if (!rc) { - FC_DBG("target abort cmd failed\n"); + FC_FCP_DBG(fsp, "target abort cmd failed\n"); rc = FAILED; } else if (fsp->state & FC_SRB_ABORTED) { - FC_DBG("target abort cmd passed\n"); + FC_FCP_DBG(fsp, "target abort cmd passed\n"); rc = SUCCESS; fc_fcp_complete_locked(fsp); } @@ -1213,7 +1208,7 @@ static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp, spin_unlock_bh(&fsp->scsi_pkt_lock); if (!rc) { - FC_DBG("lun reset failed\n"); + FC_SCSI_DBG(lp, "lun reset failed\n"); return FAILED; } @@ -1221,7 +1216,7 @@ static int fc_lun_reset(struct fc_lport *lp, struct fc_fcp_pkt *fsp, if (fsp->cdb_status != FCP_TMF_CMPL) return FAILED; - FC_DBG("lun reset to lun %u completed\n", lun); + FC_SCSI_DBG(lp, "lun reset to lun %u completed\n", lun); fc_fcp_cleanup_each_cmd(lp, id, lun, FC_CMD_ABORTED); return SUCCESS; } @@ -1388,13 +1383,13 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg) rjt = fc_frame_payload_get(fp, sizeof(*rjt)); switch (rjt->er_reason) { default: - FC_DEBUG_FCP("device %x unexpected REC reject " - "reason %d expl %d\n", - fsp->rport->port_id, rjt->er_reason, - rjt->er_explan); + FC_FCP_DBG(fsp, "device %x unexpected REC reject " + "reason %d expl %d\n", + fsp->rport->port_id, rjt->er_reason, + rjt->er_explan); /* fall through */ case ELS_RJT_UNSUP: - FC_DEBUG_FCP("device does not support REC\n"); + FC_FCP_DBG(fsp, "device does not support REC\n"); rp = fsp->rport->dd_data; /* * if we do not spport RECs or got some bogus @@ -1514,8 +1509,8 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) break; default: - FC_DBG("REC %p fid %x error unexpected error %d\n", - fsp, fsp->rport->port_id, error); + FC_FCP_DBG(fsp, "REC %p fid %x error unexpected error %d\n", + fsp, fsp->rport->port_id, error); fsp->status_code = FC_CMD_PLOGO; /* fall through */ @@ -1524,9 +1519,9 @@ static void fc_fcp_rec_error(struct fc_fcp_pkt *fsp, struct fc_frame *fp) * Assume REC or LS_ACC was lost. * The exchange manager will have aborted REC, so retry. */ - FC_DBG("REC fid %x error error %d retry %d/%d\n", - fsp->rport->port_id, error, fsp->recov_retry, - FC_MAX_RECOV_RETRY); + FC_FCP_DBG(fsp, "REC fid %x error error %d retry %d/%d\n", + fsp->rport->port_id, error, fsp->recov_retry, + FC_MAX_RECOV_RETRY); if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY) fc_fcp_rec(fsp); else @@ -2011,9 +2006,11 @@ int fc_eh_device_reset(struct scsi_cmnd *sc_cmd) if (lp->state != LPORT_ST_READY) return rc; + FC_SCSI_DBG(lp, "Resetting rport (%6x)\n", rport->port_id); + fsp = fc_fcp_pkt_alloc(lp, GFP_NOIO); if (fsp == NULL) { - FC_DBG("could not allocate scsi_pkt\n"); + printk(KERN_WARNING "libfc: could not allocate scsi_pkt\n"); sc_cmd->result = DID_NO_CONNECT << 16; goto out; } @@ -2048,17 +2045,21 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) struct fc_lport *lp = shost_priv(shost); unsigned long wait_tmo; + FC_SCSI_DBG(lp, "Resetting host\n"); + lp->tt.lport_reset(lp); wait_tmo = jiffies + FC_HOST_RESET_TIMEOUT; while (!fc_fcp_lport_queue_ready(lp) && time_before(jiffies, wait_tmo)) msleep(1000); if (fc_fcp_lport_queue_ready(lp)) { - shost_printk(KERN_INFO, shost, "Host reset succeeded.\n"); + shost_printk(KERN_INFO, shost, "libfc: Host reset succeeded " + "on port (%6x)\n", fc_host_port_id(lp->host)); return SUCCESS; } else { - shost_printk(KERN_INFO, shost, "Host reset failed. " - "lport not ready.\n"); + shost_printk(KERN_INFO, shost, "libfc: Host reset failed, " + "port (%6x) is not ready.\n", + fc_host_port_id(lp->host)); return FAILED; } } @@ -2117,7 +2118,8 @@ void fc_fcp_destroy(struct fc_lport *lp) struct fc_fcp_internal *si = fc_get_scsi_internal(lp); if (!list_empty(&si->scsi_pkt_queue)) - printk(KERN_ERR "Leaked scsi packets.\n"); + printk(KERN_ERR "libfc: Leaked SCSI packets when destroying " + "port (%6x)\n", fc_host_port_id(lp->host)); mempool_destroy(si->scsi_pkt_pool); kfree(si); @@ -2166,7 +2168,8 @@ static int __init libfc_init(void) sizeof(struct fc_fcp_pkt), 0, SLAB_HWCACHE_ALIGN, NULL); if (scsi_pkt_cachep == NULL) { - FC_DBG("Unable to allocate SRB cache...module load failed!"); + printk(KERN_ERR "libfc: Unable to allocate SRB cache, " + "module load failed!"); return -ENOMEM; } diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index e0c247724d2b..745fa5555d6a 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -101,14 +101,6 @@ #define DNS_DELAY 3 /* Discovery delay after RSCN (in seconds)*/ -static int fc_lport_debug; - -#define FC_DEBUG_LPORT(fmt...) \ - do { \ - if (fc_lport_debug) \ - FC_DBG(fmt); \ - } while (0) - static void fc_lport_error(struct fc_lport *, struct fc_frame *); static void fc_lport_enter_reset(struct fc_lport *); @@ -151,8 +143,8 @@ static void fc_lport_rport_callback(struct fc_lport *lport, struct fc_rport *rport, enum fc_rport_event event) { - FC_DEBUG_LPORT("Received a %d event for port (%6x)\n", event, - rport->port_id); + FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event, + rport->port_id); switch (event) { case RPORT_EV_CREATED: @@ -162,19 +154,19 @@ static void fc_lport_rport_callback(struct fc_lport *lport, lport->dns_rp = rport; fc_lport_enter_rpn_id(lport); } else { - FC_DEBUG_LPORT("Received an CREATED event on " - "port (%6x) for the directory " - "server, but the lport is not " - "in the DNS state, it's in the " - "%d state", rport->port_id, - lport->state); + FC_LPORT_DBG(lport, "Received an CREATED event " + "on port (%6x) for the directory " + "server, but the lport is not " + "in the DNS state, it's in the " + "%d state", rport->port_id, + lport->state); lport->tt.rport_logoff(rport); } mutex_unlock(&lport->lp_mutex); } else - FC_DEBUG_LPORT("Received an event for port (%6x) " - "which is not the directory server\n", - rport->port_id); + FC_LPORT_DBG(lport, "Received an event for port (%6x) " + "which is not the directory server\n", + rport->port_id); break; case RPORT_EV_LOGO: case RPORT_EV_FAILED: @@ -185,9 +177,9 @@ static void fc_lport_rport_callback(struct fc_lport *lport, mutex_unlock(&lport->lp_mutex); } else - FC_DEBUG_LPORT("Received an event for port (%6x) " - "which is not the directory server\n", - rport->port_id); + FC_LPORT_DBG(lport, "Received an event for port (%6x) " + "which is not the directory server\n", + rport->port_id); break; case RPORT_EV_NONE: break; @@ -363,8 +355,8 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, struct fc_lport *lport) { - FC_DEBUG_LPORT("Received RLIR request while in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", + fc_lport_state(lport)); lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL); fc_frame_free(fp); @@ -389,8 +381,8 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, void *dp; u32 f_ctl; - FC_DEBUG_LPORT("Received RLIR request while in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received RLIR request while in state %s\n", + fc_lport_state(lport)); len = fr_len(in_fp) - sizeof(struct fc_frame_header); pp = fc_frame_payload_get(in_fp, len); @@ -437,8 +429,8 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, size_t len; u32 f_ctl; - FC_DEBUG_LPORT("Received RNID request while in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received RNID request while in state %s\n", + fc_lport_state(lport)); req = fc_frame_payload_get(in_fp, sizeof(*req)); if (!req) { @@ -498,8 +490,8 @@ static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp, size_t len; u32 f_ctl; - FC_DEBUG_LPORT("Received ADISC request while in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received ADISC request while in state %s\n", + fc_lport_state(lport)); req = fc_frame_payload_get(in_fp, sizeof(*req)); if (!req) { @@ -574,8 +566,8 @@ EXPORT_SYMBOL(fc_fabric_login); */ void fc_linkup(struct fc_lport *lport) { - FC_DEBUG_LPORT("Link is up for port (%6x)\n", - fc_host_port_id(lport->host)); + printk(KERN_INFO "libfc: Link up on port (%6x)\n", + fc_host_port_id(lport->host)); mutex_lock(&lport->lp_mutex); if (!lport->link_up) { @@ -595,8 +587,8 @@ EXPORT_SYMBOL(fc_linkup); void fc_linkdown(struct fc_lport *lport) { mutex_lock(&lport->lp_mutex); - FC_DEBUG_LPORT("Link is down for port (%6x)\n", - fc_host_port_id(lport->host)); + printk(KERN_INFO "libfc: Link down on port (%6x)\n", + fc_host_port_id(lport->host)); if (lport->link_up) { lport->link_up = 0; @@ -701,12 +693,11 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) { switch (event) { case DISC_EV_SUCCESS: - FC_DEBUG_LPORT("Got a SUCCESS event for port (%6x)\n", - fc_host_port_id(lport->host)); + FC_LPORT_DBG(lport, "Discovery succeeded\n"); break; case DISC_EV_FAILED: - FC_DEBUG_LPORT("Got a FAILED event for port (%6x)\n", - fc_host_port_id(lport->host)); + printk(KERN_ERR "libfc: Discovery failed for port (%6x)\n", + fc_host_port_id(lport->host)); mutex_lock(&lport->lp_mutex); fc_lport_enter_reset(lport); mutex_unlock(&lport->lp_mutex); @@ -726,8 +717,8 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) */ static void fc_lport_enter_ready(struct fc_lport *lport) { - FC_DEBUG_LPORT("Port (%6x) entered Ready from state %s\n", - fc_host_port_id(lport->host), fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Entered READY from state %s\n", + fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_READY); @@ -762,8 +753,8 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, u32 local_fid; u32 f_ctl; - FC_DEBUG_LPORT("Received FLOGI request while in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received FLOGI request while in state %s\n", + fc_lport_state(lport)); fh = fc_frame_header_get(rx_fp); remote_fid = ntoh24(fh->fh_s_id); @@ -772,12 +763,11 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in, goto out; remote_wwpn = get_unaligned_be64(&flp->fl_wwpn); if (remote_wwpn == lport->wwpn) { - FC_DBG("FLOGI from port with same WWPN %llx " - "possible configuration error\n", - (unsigned long long)remote_wwpn); + printk(KERN_WARNING "libfc: Received FLOGI from port " + "with same WWPN %llx\n", remote_wwpn); goto out; } - FC_DBG("FLOGI from port WWPN %llx\n", (unsigned long long)remote_wwpn); + FC_LPORT_DBG(lport, "FLOGI from port WWPN %llx\n", remote_wwpn); /* * XXX what is the right thing to do for FIDs? @@ -909,7 +899,8 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, } } } else { - FC_DBG("dropping invalid frame (eof %x)\n", fr_eof(fp)); + FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", + fr_eof(fp)); fc_frame_free(fp); } mutex_unlock(&lport->lp_mutex); @@ -947,8 +938,8 @@ EXPORT_SYMBOL(fc_lport_reset); */ static void fc_lport_enter_reset(struct fc_lport *lport) { - FC_DEBUG_LPORT("Port (%6x) entered RESET state from %s state\n", - fc_host_port_id(lport->host), fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Entered RESET state from %s state\n", + fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_RESET); @@ -982,9 +973,9 @@ static void fc_lport_enter_reset(struct fc_lport *lport) static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) { unsigned long delay = 0; - FC_DEBUG_LPORT("Error %ld in state %s, retries %d\n", - PTR_ERR(fp), fc_lport_state(lport), - lport->retry_count); + FC_LPORT_DBG(lport, "Error %ld in state %s, retries %d\n", + PTR_ERR(fp), fc_lport_state(lport), + lport->retry_count); if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) { /* @@ -1040,11 +1031,11 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&lport->lp_mutex); - FC_DEBUG_LPORT("Received a RFT_ID response\n"); + FC_LPORT_DBG(lport, "Received a RFT_ID response\n"); if (lport->state != LPORT_ST_RFT_ID) { - FC_DBG("Received a RFT_ID response, but in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received a RFT_ID response, but in state " + "%s\n", fc_lport_state(lport)); if (IS_ERR(fp)) goto err; goto out; @@ -1094,11 +1085,11 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&lport->lp_mutex); - FC_DEBUG_LPORT("Received a RPN_ID response\n"); + FC_LPORT_DBG(lport, "Received a RPN_ID response\n"); if (lport->state != LPORT_ST_RPN_ID) { - FC_DBG("Received a RPN_ID response, but in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received a RPN_ID response, but in state " + "%s\n", fc_lport_state(lport)); if (IS_ERR(fp)) goto err; goto out; @@ -1146,11 +1137,11 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&lport->lp_mutex); - FC_DEBUG_LPORT("Received a SCR response\n"); + FC_LPORT_DBG(lport, "Received a SCR response\n"); if (lport->state != LPORT_ST_SCR) { - FC_DBG("Received a SCR response, but in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received a SCR response, but in state " + "%s\n", fc_lport_state(lport)); if (IS_ERR(fp)) goto err; goto out; @@ -1184,8 +1175,8 @@ static void fc_lport_enter_scr(struct fc_lport *lport) { struct fc_frame *fp; - FC_DEBUG_LPORT("Port (%6x) entered SCR state from %s state\n", - fc_host_port_id(lport->host), fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Entered SCR state from %s state\n", + fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_SCR); @@ -1213,8 +1204,8 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport) struct fc_ns_fts *lps; int i; - FC_DEBUG_LPORT("Port (%6x) entered RFT_ID state from %s state\n", - fc_host_port_id(lport->host), fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Entered RFT_ID state from %s state\n", + fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_RFT_ID); @@ -1253,8 +1244,8 @@ static void fc_lport_enter_rpn_id(struct fc_lport *lport) { struct fc_frame *fp; - FC_DEBUG_LPORT("Port (%6x) entered RPN_ID state from %s state\n", - fc_host_port_id(lport->host), fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Entered RPN_ID state from %s state\n", + fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_RPN_ID); @@ -1294,8 +1285,8 @@ static void fc_lport_enter_dns(struct fc_lport *lport) dp.ids.roles = FC_RPORT_ROLE_UNKNOWN; dp.lp = lport; - FC_DEBUG_LPORT("Port (%6x) entered DNS state from %s state\n", - fc_host_port_id(lport->host), fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Entered DNS state from %s state\n", + fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_DNS); @@ -1374,11 +1365,11 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&lport->lp_mutex); - FC_DEBUG_LPORT("Received a LOGO response\n"); + FC_LPORT_DBG(lport, "Received a LOGO response\n"); if (lport->state != LPORT_ST_LOGO) { - FC_DBG("Received a LOGO response, but in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received a LOGO response, but in state " + "%s\n", fc_lport_state(lport)); if (IS_ERR(fp)) goto err; goto out; @@ -1413,8 +1404,8 @@ static void fc_lport_enter_logo(struct fc_lport *lport) struct fc_frame *fp; struct fc_els_logo *logo; - FC_DEBUG_LPORT("Port (%6x) entered LOGO state from %s state\n", - fc_host_port_id(lport->host), fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Entered LOGO state from %s state\n", + fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_LOGO); @@ -1456,11 +1447,11 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&lport->lp_mutex); - FC_DEBUG_LPORT("Received a FLOGI response\n"); + FC_LPORT_DBG(lport, "Received a FLOGI response\n"); if (lport->state != LPORT_ST_FLOGI) { - FC_DBG("Received a FLOGI response, but in state %s\n", - fc_lport_state(lport)); + FC_LPORT_DBG(lport, "Received a FLOGI response, but in state " + "%s\n", fc_lport_state(lport)); if (IS_ERR(fp)) goto err; goto out; @@ -1475,7 +1466,8 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, did = ntoh24(fh->fh_d_id); if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { - FC_DEBUG_LPORT("Assigned fid %x\n", did); + printk(KERN_INFO "libfc: Assigned FID (%6x) in FLOGI response\n", + did); fc_host_port_id(lport->host) = did; flp = fc_frame_payload_get(fp, sizeof(*flp)); @@ -1494,7 +1486,8 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, if (e_d_tov > lport->e_d_tov) lport->e_d_tov = e_d_tov; lport->r_a_tov = 2 * e_d_tov; - FC_DBG("Point-to-Point mode\n"); + printk(KERN_INFO "libfc: Port (%6x) entered " + "point to point mode\n", did); fc_lport_ptp_setup(lport, ntoh24(fh->fh_s_id), get_unaligned_be64( &flp->fl_wwpn), @@ -1517,7 +1510,7 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, } } } else { - FC_DBG("bad FLOGI response\n"); + FC_LPORT_DBG(lport, "Bad FLOGI response\n"); } out: @@ -1537,7 +1530,8 @@ void fc_lport_enter_flogi(struct fc_lport *lport) { struct fc_frame *fp; - FC_DEBUG_LPORT("Processing FLOGI state\n"); + FC_LPORT_DBG(lport, "Entered FLOGI state from %s state\n", + fc_lport_state(lport)); fc_lport_state_enter(lport, LPORT_ST_FLOGI); diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 7bfbff7e0efb..7162385f52eb 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -55,14 +55,6 @@ #include #include -static int fc_rport_debug; - -#define FC_DEBUG_RPORT(fmt...) \ - do { \ - if (fc_rport_debug) \ - FC_DBG(fmt); \ - } while (0) - struct workqueue_struct *rport_event_queue; static void fc_rport_enter_plogi(struct fc_rport *); @@ -97,7 +89,7 @@ static const char *fc_rport_state_names[] = { static void fc_rport_rogue_destroy(struct device *dev) { struct fc_rport *rport = dev_to_rport(dev); - FC_DEBUG_RPORT("Destroying rogue rport (%6x)\n", rport->port_id); + FC_RPORT_DBG(rport, "Destroying rogue rport\n"); kfree(rport); } @@ -263,8 +255,8 @@ static void fc_rport_work(struct work_struct *work) fc_rport_state_enter(new_rport, RPORT_ST_READY); } else { - FC_DBG("Failed to create the rport for port " - "(%6x).\n", ids.port_id); + printk(KERN_WARNING "libfc: Failed to allocate " + " memory for rport (%6x)\n", ids.port_id); event = RPORT_EV_FAILED; } if (rport->port_id != FC_FID_DIR_SERV) @@ -309,7 +301,7 @@ int fc_rport_login(struct fc_rport *rport) mutex_lock(&rdata->rp_mutex); - FC_DEBUG_RPORT("Login to port (%6x)\n", rport->port_id); + FC_RPORT_DBG(rport, "Login to port\n"); fc_rport_enter_plogi(rport); @@ -329,16 +321,13 @@ int fc_rport_login(struct fc_rport *rport) int fc_rport_logoff(struct fc_rport *rport) { struct fc_rport_libfc_priv *rdata = rport->dd_data; - struct fc_lport *lport = rdata->local_port; mutex_lock(&rdata->rp_mutex); - FC_DEBUG_RPORT("Remove port (%6x)\n", rport->port_id); + FC_RPORT_DBG(rport, "Remove port\n"); if (rdata->rp_state == RPORT_ST_NONE) { - FC_DEBUG_RPORT("(%6x): Port (%6x) in NONE state," - " not removing", fc_host_port_id(lport->host), - rport->port_id); + FC_RPORT_DBG(rport, "Port in NONE state, not removing\n"); mutex_unlock(&rdata->rp_mutex); goto out; } @@ -379,7 +368,7 @@ static void fc_rport_enter_ready(struct fc_rport *rport) fc_rport_state_enter(rport, RPORT_ST_READY); - FC_DEBUG_RPORT("Port (%6x) is Ready\n", rport->port_id); + FC_RPORT_DBG(rport, "Port is Ready\n"); rdata->event = RPORT_EV_CREATED; queue_work(rport_event_queue, &rdata->event_work); @@ -436,8 +425,8 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp) { struct fc_rport_libfc_priv *rdata = rport->dd_data; - FC_DEBUG_RPORT("Error %ld in state %s, retries %d\n", - PTR_ERR(fp), fc_rport_state(rport), rdata->retries); + FC_RPORT_DBG(rport, "Error %ld in state %s, retries %d\n", + PTR_ERR(fp), fc_rport_state(rport), rdata->retries); switch (rdata->rp_state) { case RPORT_ST_PLOGI: @@ -479,8 +468,8 @@ static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp) return fc_rport_error(rport, fp); if (rdata->retries < rdata->local_port->max_rport_retry_count) { - FC_DEBUG_RPORT("Error %ld in state %s, retrying\n", - PTR_ERR(fp), fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Error %ld in state %s, retrying\n", + PTR_ERR(fp), fc_rport_state(rport)); rdata->retries++; /* no additional delay on exchange timeouts */ if (PTR_ERR(fp) == -FC_EX_TIMEOUT) @@ -517,12 +506,11 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&rdata->rp_mutex); - FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", - rport->port_id); + FC_RPORT_DBG(rport, "Received a PLOGI response\n"); if (rdata->rp_state != RPORT_ST_PLOGI) { - FC_DBG("Received a PLOGI response, but in state %s\n", - fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Received a PLOGI response, but in state " + "%s\n", fc_rport_state(rport)); if (IS_ERR(fp)) goto err; goto out; @@ -583,8 +571,8 @@ static void fc_rport_enter_plogi(struct fc_rport *rport) struct fc_lport *lport = rdata->local_port; struct fc_frame *fp; - FC_DEBUG_RPORT("Port (%6x) entered PLOGI state from %s state\n", - rport->port_id, fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Port entered PLOGI state from %s state\n", + fc_rport_state(rport)); fc_rport_state_enter(rport, RPORT_ST_PLOGI); @@ -628,12 +616,11 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&rdata->rp_mutex); - FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", - rport->port_id); + FC_RPORT_DBG(rport, "Received a PRLI response\n"); if (rdata->rp_state != RPORT_ST_PRLI) { - FC_DBG("Received a PRLI response, but in state %s\n", - fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Received a PRLI response, but in state " + "%s\n", fc_rport_state(rport)); if (IS_ERR(fp)) goto err; goto out; @@ -663,7 +650,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, fc_rport_enter_rtv(rport); } else { - FC_DBG("Bad ELS response\n"); + FC_RPORT_DBG(rport, "Bad ELS response for PRLI command\n"); rdata->event = RPORT_EV_FAILED; fc_rport_state_enter(rport, RPORT_ST_NONE); queue_work(rport_event_queue, &rdata->event_work); @@ -695,12 +682,11 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&rdata->rp_mutex); - FC_DEBUG_RPORT("Received a LOGO response from port (%6x)\n", - rport->port_id); + FC_RPORT_DBG(rport, "Received a LOGO response\n"); if (rdata->rp_state != RPORT_ST_LOGO) { - FC_DEBUG_RPORT("Received a LOGO response, but in state %s\n", - fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Received a LOGO response, but in state " + "%s\n", fc_rport_state(rport)); if (IS_ERR(fp)) goto err; goto out; @@ -715,7 +701,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, if (op == ELS_LS_ACC) { fc_rport_enter_rtv(rport); } else { - FC_DBG("Bad ELS response\n"); + FC_RPORT_DBG(rport, "Bad ELS response for LOGO command\n"); rdata->event = RPORT_EV_LOGO; fc_rport_state_enter(rport, RPORT_ST_NONE); queue_work(rport_event_queue, &rdata->event_work); @@ -745,8 +731,8 @@ static void fc_rport_enter_prli(struct fc_rport *rport) } *pp; struct fc_frame *fp; - FC_DEBUG_RPORT("Port (%6x) entered PRLI state from %s state\n", - rport->port_id, fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Port entered PRLI state from %s state\n", + fc_rport_state(rport)); fc_rport_state_enter(rport, RPORT_ST_PRLI); @@ -784,12 +770,11 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, mutex_lock(&rdata->rp_mutex); - FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", - rport->port_id); + FC_RPORT_DBG(rport, "Received a RTV response\n"); if (rdata->rp_state != RPORT_ST_RTV) { - FC_DBG("Received a RTV response, but in state %s\n", - fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Received a RTV response, but in state " + "%s\n", fc_rport_state(rport)); if (IS_ERR(fp)) goto err; goto out; @@ -844,8 +829,8 @@ static void fc_rport_enter_rtv(struct fc_rport *rport) struct fc_rport_libfc_priv *rdata = rport->dd_data; struct fc_lport *lport = rdata->local_port; - FC_DEBUG_RPORT("Port (%6x) entered RTV state from %s state\n", - rport->port_id, fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Port entered RTV state from %s state\n", + fc_rport_state(rport)); fc_rport_state_enter(rport, RPORT_ST_RTV); @@ -875,8 +860,8 @@ static void fc_rport_enter_logo(struct fc_rport *rport) struct fc_lport *lport = rdata->local_port; struct fc_frame *fp; - FC_DEBUG_RPORT("Port (%6x) entered LOGO state from %s state\n", - rport->port_id, fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Port entered LOGO state from %s state\n", + fc_rport_state(rport)); fc_rport_state_enter(rport, RPORT_ST_LOGO); @@ -983,14 +968,13 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, fh = fc_frame_header_get(fp); - FC_DEBUG_RPORT("Received PLOGI request from port (%6x) " - "while in state %s\n", ntoh24(fh->fh_s_id), - fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Received PLOGI request while in state %s\n", + fc_rport_state(rport)); sid = ntoh24(fh->fh_s_id); pl = fc_frame_payload_get(fp, sizeof(*pl)); if (!pl) { - FC_DBG("incoming PLOGI from %x too short\n", sid); + FC_RPORT_DBG(rport, "Received PLOGI too short\n"); WARN_ON(1); /* XXX TBD: send reject? */ fc_frame_free(fp); @@ -1012,26 +996,26 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, */ switch (rdata->rp_state) { case RPORT_ST_INIT: - FC_DEBUG_RPORT("incoming PLOGI from %6x wwpn %llx state INIT " - "- reject\n", sid, (unsigned long long)wwpn); + FC_RPORT_DBG(rport, "Received PLOGI, wwpn %llx state INIT " + "- reject\n", (unsigned long long)wwpn); reject = ELS_RJT_UNSUP; break; case RPORT_ST_PLOGI: - FC_DEBUG_RPORT("incoming PLOGI from %x in PLOGI state %d\n", - sid, rdata->rp_state); + FC_RPORT_DBG(rport, "Received PLOGI in PLOGI state %d\n", + rdata->rp_state); if (wwpn < lport->wwpn) reject = ELS_RJT_INPROG; break; case RPORT_ST_PRLI: case RPORT_ST_READY: - FC_DEBUG_RPORT("incoming PLOGI from %x in logged-in state %d " - "- ignored for now\n", sid, rdata->rp_state); + FC_RPORT_DBG(rport, "Received PLOGI in logged-in state %d " + "- ignored for now\n", rdata->rp_state); /* XXX TBD - should reset */ break; case RPORT_ST_NONE: default: - FC_DEBUG_RPORT("incoming PLOGI from %x in unexpected " - "state %d\n", sid, rdata->rp_state); + FC_RPORT_DBG(rport, "Received PLOGI in unexpected " + "state %d\n", rdata->rp_state); fc_frame_free(fp); return; break; @@ -1115,9 +1099,8 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport, fh = fc_frame_header_get(rx_fp); - FC_DEBUG_RPORT("Received PRLI request from port (%6x) " - "while in state %s\n", ntoh24(fh->fh_s_id), - fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Received PRLI request while in state %s\n", + fc_rport_state(rport)); switch (rdata->rp_state) { case RPORT_ST_PRLI: @@ -1252,9 +1235,8 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp, fh = fc_frame_header_get(fp); - FC_DEBUG_RPORT("Received PRLO request from port (%6x) " - "while in state %s\n", ntoh24(fh->fh_s_id), - fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Received PRLO request while in state %s\n", + fc_rport_state(rport)); if (rdata->rp_state == RPORT_ST_NONE) { fc_frame_free(fp); @@ -1286,9 +1268,8 @@ static void fc_rport_recv_logo_req(struct fc_rport *rport, struct fc_seq *sp, fh = fc_frame_header_get(fp); - FC_DEBUG_RPORT("Received LOGO request from port (%6x) " - "while in state %s\n", ntoh24(fh->fh_s_id), - fc_rport_state(rport)); + FC_RPORT_DBG(rport, "Received LOGO request while in state %s\n", + fc_rport_state(rport)); if (rdata->rp_state == RPORT_ST_NONE) { fc_frame_free(fp); @@ -1308,7 +1289,6 @@ static void fc_rport_flush_queue(void) flush_workqueue(rport_event_queue); } - int fc_rport_init(struct fc_lport *lport) { if (!lport->tt.rport_create) diff --git a/include/scsi/fc_encode.h b/include/scsi/fc_encode.h index 6300f556bce5..a0ff61c3e935 100644 --- a/include/scsi/fc_encode.h +++ b/include/scsi/fc_encode.h @@ -107,7 +107,6 @@ static inline int fc_ct_fill(struct fc_lport *lport, struct fc_frame *fp, break; default: - FC_DBG("Invalid op code %x \n", op); return -EINVAL; } *r_ctl = FC_RCTL_DD_UNSOL_CTL; @@ -298,7 +297,6 @@ static inline int fc_els_fill(struct fc_lport *lport, struct fc_rport *rport, break; default: - FC_DBG("Invalid op code %x \n", op); return -EINVAL; } diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index ebdd9f4cf070..b92584a8843a 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -34,17 +34,72 @@ #include -#define LIBFC_DEBUG - -#ifdef LIBFC_DEBUG -/* Log messages */ -#define FC_DBG(fmt, args...) \ - do { \ - printk(KERN_INFO "%s " fmt, __func__, ##args); \ - } while (0) -#else -#define FC_DBG(fmt, args...) -#endif +#define FC_LIBFC_LOGGING 0x01 /* General logging, not categorized */ +#define FC_LPORT_LOGGING 0x02 /* lport layer logging */ +#define FC_DISC_LOGGING 0x04 /* discovery layer logging */ +#define FC_RPORT_LOGGING 0x08 /* rport layer logging */ +#define FC_FCP_LOGGING 0x10 /* I/O path logging */ +#define FC_EM_LOGGING 0x20 /* Exchange Manager logging */ +#define FC_EXCH_LOGGING 0x40 /* Exchange/Sequence logging */ +#define FC_SCSI_LOGGING 0x80 /* SCSI logging (mostly error handling) */ + +extern unsigned int fc_debug_logging; + +#define FC_CHECK_LOGGING(LEVEL, CMD) \ +do { \ + if (unlikely(fc_debug_logging & LEVEL)) \ + do { \ + CMD; \ + } while (0); \ +} while (0); + +#define FC_LIBFC_DBG(fmt, args...) \ + FC_CHECK_LOGGING(FC_LIBFC_LOGGING, \ + printk(KERN_INFO "libfc: " fmt, ##args);) + +#define FC_LPORT_DBG(lport, fmt, args...) \ + FC_CHECK_LOGGING(FC_LPORT_LOGGING, \ + printk(KERN_INFO "lport: %6x: " fmt, \ + fc_host_port_id(lport->host), ##args);) + +#define FC_DISC_DBG(disc, fmt, args...) \ + FC_CHECK_LOGGING(FC_DISC_LOGGING, \ + printk(KERN_INFO "disc: %6x: " fmt, \ + fc_host_port_id(disc->lport->host), \ + ##args);) + +#define FC_RPORT_DBG(rport, fmt, args...) \ +do { \ + struct fc_rport_libfc_priv *rdata = rport->dd_data; \ + struct fc_lport *lport = rdata->local_port; \ + FC_CHECK_LOGGING(FC_RPORT_LOGGING, \ + printk(KERN_INFO "rport: %6x: %6x: " fmt, \ + fc_host_port_id(lport->host), \ + rport->port_id, ##args);) \ +} while (0); + +#define FC_FCP_DBG(pkt, fmt, args...) \ + FC_CHECK_LOGGING(FC_FCP_LOGGING, \ + printk(KERN_INFO "fcp: %6x: %6x: " fmt, \ + fc_host_port_id(pkt->lp->host), \ + pkt->rport->port_id, ##args);) + +#define FC_EM_DBG(em, fmt, args...) \ + FC_CHECK_LOGGING(FC_EM_LOGGING, \ + printk(KERN_INFO "em: %6x: " fmt, \ + fc_host_port_id(em->lp->host), \ + ##args);) + +#define FC_EXCH_DBG(exch, fmt, args...) \ + FC_CHECK_LOGGING(FC_EXCH_LOGGING, \ + printk(KERN_INFO "exch: %6x: %4x: " fmt, \ + fc_host_port_id(exch->lp->host), \ + exch->xid, ##args);) + +#define FC_SCSI_DBG(lport, fmt, args...) \ + FC_CHECK_LOGGING(FC_SCSI_LOGGING, \ + printk(KERN_INFO "scsi: %6x: " fmt, \ + fc_host_port_id(lport->host), ##args);) /* * libfc error codes -- cgit v1.2.3 From f1d7fb7a8ab55357b6c7d44a53f644a043680ed1 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 18 Jun 2009 09:06:52 -0500 Subject: ibmvfc: Process async events before command responses Since async events could indicate changes to link status, or events which could affect decisions made during discovery, we should process async events prior to command completion responses. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index b4b805e8d7db..497a4cc4d9ef 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2783,27 +2783,27 @@ static void ibmvfc_tasklet(void *data) spin_lock_irqsave(vhost->host->host_lock, flags); while (!done) { - /* Pull all the valid messages off the CRQ */ - while ((crq = ibmvfc_next_crq(vhost)) != NULL) { - ibmvfc_handle_crq(crq, vhost); - crq->valid = 0; - } - /* Pull all the valid messages off the async CRQ */ while ((async = ibmvfc_next_async_crq(vhost)) != NULL) { ibmvfc_handle_async(async, vhost); async->valid = 0; } - vio_enable_interrupts(vdev); - if ((crq = ibmvfc_next_crq(vhost)) != NULL) { - vio_disable_interrupts(vdev); + /* Pull all the valid messages off the CRQ */ + while ((crq = ibmvfc_next_crq(vhost)) != NULL) { ibmvfc_handle_crq(crq, vhost); crq->valid = 0; - } else if ((async = ibmvfc_next_async_crq(vhost)) != NULL) { + } + + vio_enable_interrupts(vdev); + if ((async = ibmvfc_next_async_crq(vhost)) != NULL) { vio_disable_interrupts(vdev); ibmvfc_handle_async(async, vhost); async->valid = 0; + } else if ((crq = ibmvfc_next_crq(vhost)) != NULL) { + vio_disable_interrupts(vdev); + ibmvfc_handle_crq(crq, vhost); + crq->valid = 0; } else done = 1; } -- cgit v1.2.3 From 017b2ae33c0fc7d70320cc7f1cce0efb6ce8d929 Mon Sep 17 00:00:00 2001 From: Brian King Date: Thu, 18 Jun 2009 09:06:55 -0500 Subject: ibmvfc: Fix endless PRLI loop in discovery Fixes a problem seen where sending a PRLI to a target resulted in it sending a LOGO. This caused the ibmvfc driver to go back through discovery again, which caused another PRLI attempt, which caused another LOGO. Fix this behavior by ignoring LOGO if we haven't even logged into the target yet. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 16 ++++++++++++---- drivers/scsi/ibmvscsi/ibmvfc.h | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 497a4cc4d9ef..166d96450a0e 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2254,10 +2254,13 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, continue; if (crq->node_name && tgt->ids.node_name != crq->node_name) continue; - ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + if (tgt->need_login && crq->event == IBMVFC_AE_ELS_LOGO) + tgt->logo_rcvd = 1; + if (!tgt->need_login || crq->event == IBMVFC_AE_ELS_PLOGI) { + ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); + ibmvfc_reinit_host(vhost); + } } - - ibmvfc_reinit_host(vhost); break; case IBMVFC_AE_LINK_DOWN: case IBMVFC_AE_ADAPTER_FAILED: @@ -2927,7 +2930,11 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) break; case IBMVFC_MAD_FAILED: default: - if (ibmvfc_retry_cmd(rsp->status, rsp->error)) + if ((rsp->status & IBMVFC_VIOS_FAILURE) && rsp->error == IBMVFC_PLOGI_REQUIRED) + level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); + else if (tgt->logo_rcvd) + level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); + else if (ibmvfc_retry_cmd(rsp->status, rsp->error)) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); else ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); @@ -3054,6 +3061,7 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt) return; kref_get(&tgt->kref); + tgt->logo_rcvd = 0; evt = ibmvfc_get_event(vhost); vhost->discovery_threads++; ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index c2668d7d67f5..007fa1c9ef14 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -605,6 +605,7 @@ struct ibmvfc_target { int need_login; int add_rport; int init_retries; + int logo_rcvd; u32 cancel_key; struct ibmvfc_service_parms service_parms; struct ibmvfc_service_parms service_parms_change; -- cgit v1.2.3 From 5e2fb917920c62c5ad260962471aeb578b52ac40 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 18 Jun 2009 21:03:23 +0200 Subject: explain the hidden scsi_wait_scan Kconfig variable People keep sending patches to expose CONFIG_SCSI_WAIT_SCAN as a tunable item. These patches aren't accepted upstream, so let's stop the ongoing irritation of people due to the unconditionally installed module and its Kconfig symbol. Signed-off-by: Stefan Richter Signed-off-by: James Bottomley --- drivers/scsi/Kconfig | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 6a19ed9a1194..9c23122f755f 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -258,10 +258,21 @@ config SCSI_SCAN_ASYNC or async on the kernel's command line. config SCSI_WAIT_SCAN - tristate + tristate # No prompt here, this is an invisible symbol. default m depends on SCSI depends on MODULES +# scsi_wait_scan is a loadable module which waits until all the async scans are +# complete. The idea is to use it in initrd/ initramfs scripts. You modprobe +# it after all the modprobes of the root SCSI drivers and it will wait until +# they have all finished scanning their buses before allowing the boot to +# proceed. (This method is not applicable if targets boot independently in +# parallel with the initiator, or with transports with non-deterministic target +# discovery schemes, or if a transport driver does not support scsi_wait_scan.) +# +# This symbol is not exposed as a prompt because little is to be gained by +# disabling it, whereas people who accidentally switch it off may wonder why +# their mkinitrd gets into trouble. menu "SCSI Transports" depends on SCSI -- cgit v1.2.3 From 75be63bcf73ebdd1fdc1d49f6bf2d1326a1ba7de Mon Sep 17 00:00:00 2001 From: John Stoffel Date: Fri, 19 Jun 2009 16:08:58 -0400 Subject: sym53c8xx: ratelimit parity errors This makes a huge difference when you have a serial console on bootup to limit these messages to a sane number. Signed-off-by: John Stoffel Signed-off-by: James Bottomley --- drivers/scsi/sym53c8xx_2/sym_hipd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index 69ad4945c936..297deb817a5d 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -2321,8 +2321,9 @@ static void sym_int_par (struct sym_hcb *np, u_short sist) int phase = cmd & 7; struct sym_ccb *cp = sym_ccb_from_dsa(np, dsa); - printf("%s: SCSI parity error detected: SCR1=%d DBC=%x SBCL=%x\n", - sym_name(np), hsts, dbc, sbcl); + if (printk_ratelimit()) + printf("%s: SCSI parity error detected: SCR1=%d DBC=%x SBCL=%x\n", + sym_name(np), hsts, dbc, sbcl); /* * Check that the chip is connected to the SCSI BUS. -- cgit v1.2.3 From b5c6f77680f4ff1775838fcedfdd6026bf5ad777 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 19 Jun 2009 16:26:53 -0700 Subject: fc_transport: The softirq_done function registration for BSG request Registered the softirq_done function, since this is requried iby an request using block level request timeout functionality. This function will be called by the block layer as part of time out clean process to release the BSG request. Moved some of the BSG request completion activities to softirq_done routine to take care of both normal and timout completions. Signed-off-by: Giridhar Malavali Acked-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 3f64d93b6c8b..453d9e658eb6 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3397,7 +3397,6 @@ fc_destroy_bsgjob(struct fc_bsg_job *job) kfree(job); } - /** * fc_bsg_jobdone - completion routine for bsg requests that the LLD has * completed @@ -3408,15 +3407,10 @@ fc_bsg_jobdone(struct fc_bsg_job *job) { struct request *req = job->req; struct request *rsp = req->next_rq; - unsigned long flags; int err; - spin_lock_irqsave(&job->job_lock, flags); - job->state_flags |= FC_RQST_STATE_DONE; - job->ref_cnt--; - spin_unlock_irqrestore(&job->job_lock, flags); - err = job->req->errors = job->reply->result; + if (err < 0) /* we're only returning the result field in the reply */ job->req->sense_len = sizeof(uint32_t); @@ -3433,13 +3427,27 @@ fc_bsg_jobdone(struct fc_bsg_job *job) rsp->resid_len -= min(job->reply->reply_payload_rcv_len, rsp->resid_len); } + blk_complete_request(req); +} + +/** + * fc_bsg_softirq_done - softirq done routine for destroying the bsg requests + * @req: BSG request that holds the job to be destroyed + */ +static void fc_bsg_softirq_done(struct request *rq) +{ + struct fc_bsg_job *job = rq->special; + unsigned long flags; - blk_end_request_all(req, err); + spin_lock_irqsave(&job->job_lock, flags); + job->state_flags |= FC_RQST_STATE_DONE; + job->ref_cnt--; + spin_unlock_irqrestore(&job->job_lock, flags); + blk_end_request_all(rq, rq->errors); fc_destroy_bsgjob(job); } - /** * fc_bsg_job_timeout - handler for when a bsg request timesout * @req: request that timed out @@ -3471,19 +3479,10 @@ fc_bsg_job_timeout(struct request *req) "abort failed with status %d\n", err); } - if (!done) { - spin_lock_irqsave(&job->job_lock, flags); - job->ref_cnt--; - spin_unlock_irqrestore(&job->job_lock, flags); - fc_destroy_bsgjob(job); - } - /* the blk_end_sync_io() doesn't check the error */ return BLK_EH_HANDLED; } - - static int fc_bsg_map_buffer(struct fc_bsg_buffer *buf, struct request *req) { @@ -3879,6 +3878,7 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host) q->queuedata = shost; queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q); + blk_queue_softirq_done(q, fc_bsg_softirq_done); blk_queue_rq_timed_out(q, fc_bsg_job_timeout); blk_queue_rq_timeout(q, FC_DEFAULT_BSG_TIMEOUT); @@ -3924,6 +3924,7 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport) q->queuedata = rport; queue_flag_set_unlocked(QUEUE_FLAG_BIDI, q); + blk_queue_softirq_done(q, fc_bsg_softirq_done); blk_queue_rq_timed_out(q, fc_bsg_job_timeout); blk_queue_rq_timeout(q, BLK_DEFAULT_SG_TIMEOUT); -- cgit v1.2.3 From 47e7e89ed029780adf2cc0cf506fcd4c2d5ca1e2 Mon Sep 17 00:00:00 2001 From: Giridhar Malavali Date: Fri, 19 Jun 2009 16:26:54 -0700 Subject: fc_transport: Selective return value from BSG timeout function The return value from BSG timout function should be based on the state of the BSG job. This helps block layer to take selective actions to clean up BSG job. Signed-off-by: Giridhar Malavali Acked-by: FUJITA Tomonori Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 453d9e658eb6..140c50c8a5d2 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3480,7 +3480,10 @@ fc_bsg_job_timeout(struct request *req) } /* the blk_end_sync_io() doesn't check the error */ - return BLK_EH_HANDLED; + if (done) + return BLK_EH_NOT_HANDLED; + else + return BLK_EH_HANDLED; } static int -- cgit v1.2.3 From 24add1c4326ce5ca22e7af8b84bb113cd48efac9 Mon Sep 17 00:00:00 2001 From: Jaswinder Singh Rajput Date: Sat, 20 Jun 2009 13:29:21 +0530 Subject: scsi_transport_iscsi: return -EOVERFLOW for Too many iscsi targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setting err as -EOVERFLOW for Too many iscsi targets. Also fixes a spurious compiler warning for gcc 4.3.3 and gcc 4.4 : CC drivers/scsi/scsi_transport_iscsi.o drivers/scsi/scsi_transport_iscsi.c: In function ‘iscsi_add_session’: drivers/scsi/scsi_transport_iscsi.c:678: warning: ‘err’ may be used uninitialized in this function Signed-off-by: Jaswinder Singh Rajput Acked-by: Mike Christie Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_iscsi.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index f3e664628d7a..783e33c65eb7 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -692,6 +692,7 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id) "Too many iscsi targets. Max " "number of targets is %d.\n", ISCSI_MAX_TARGET - 1); + err = -EOVERFLOW; goto release_host; } } -- cgit v1.2.3 From b391277a56b9eaaff4474339c703e574ed7fab5b Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Thu, 18 Jun 2009 09:57:18 +0200 Subject: sd, sr: fix Driver 'sd' needs updating message If a SCSI ULD driver sets blk_queue_prep_rq(), it should clean it up itself on remove(), and not from the bus callbacks. This removes the need to hook into bus->remove(), which should not be used at the same time as driver->remove(). [jejb: fix sdkp initialisation problem due to mismerge] Signed-off-by: Hannes Reinecke Signed-off-by: Kay Sievers Signed-off-by: James Bottomley --- drivers/scsi/scsi_lib.c | 1 + drivers/scsi/scsi_priv.h | 1 - drivers/scsi/scsi_sysfs.c | 17 ----------------- drivers/scsi/sd.c | 1 + drivers/scsi/sr.c | 1 + include/scsi/scsi_driver.h | 1 + 6 files changed, 4 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 30f3275e119e..f3c40898fc7d 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1207,6 +1207,7 @@ int scsi_prep_fn(struct request_queue *q, struct request *req) ret = scsi_setup_blk_pc_cmnd(sdev, req); return scsi_prep_return(q, req, ret); } +EXPORT_SYMBOL(scsi_prep_fn); /* * scsi_dev_queue_ready: if we can send requests to sdev, return 1 else diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 00264aab8c8a..021e503c8c44 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -87,7 +87,6 @@ extern int scsi_init_queue(void); extern void scsi_exit_queue(void); struct request_queue; struct request; -extern int scsi_prep_fn(struct request_queue *, struct request *); extern struct kmem_cache *scsi_sdb_cache; /* scsi_proc.c */ diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index fa4711d12744..91482f2dcc50 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -420,29 +420,12 @@ static int scsi_bus_resume(struct device * dev) return err; } -static int scsi_bus_remove(struct device *dev) -{ - struct device_driver *drv = dev->driver; - struct scsi_device *sdev = to_scsi_device(dev); - int err = 0; - - /* reset the prep_fn back to the default since the - * driver may have altered it and it's being removed */ - blk_queue_prep_rq(sdev->request_queue, scsi_prep_fn); - - if (drv && drv->remove) - err = drv->remove(dev); - - return 0; -} - struct bus_type scsi_bus_type = { .name = "scsi", .match = scsi_bus_match, .uevent = scsi_bus_uevent, .suspend = scsi_bus_suspend, .resume = scsi_bus_resume, - .remove = scsi_bus_remove, }; EXPORT_SYMBOL_GPL(scsi_bus_type); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index e4ef11af18a2..5616cd780ff3 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2123,6 +2123,7 @@ static int sd_remove(struct device *dev) async_synchronize_full(); sdkp = dev_get_drvdata(dev); + blk_queue_prep_rq(sdkp->device->request_queue, scsi_prep_fn); device_del(&sdkp->dev); del_gendisk(sdkp->disk); sd_shutdown(dev); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index cd350dfc1216..cce0fe4c8a3b 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -881,6 +881,7 @@ static int sr_remove(struct device *dev) { struct scsi_cd *cd = dev_get_drvdata(dev); + blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn); del_gendisk(cd->disk); mutex_lock(&sr_ref_mutex); diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h index 1f5ca7f62116..9fd6702f02e2 100644 --- a/include/scsi/scsi_driver.h +++ b/include/scsi/scsi_driver.h @@ -32,5 +32,6 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req); int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req); int scsi_prep_state_check(struct scsi_device *sdev, struct request *req); int scsi_prep_return(struct request_queue *q, struct request *req, int ret); +int scsi_prep_fn(struct request_queue *, struct request *); #endif /* _SCSI_SCSI_DRIVER_H */ -- cgit v1.2.3 From 3c559ea8fd003962d9a28c64b2dd5c6d83ca6edb Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 21 Jun 2009 12:11:43 -0500 Subject: [SCSI] scsi_transport_fc: replace BUS_ID_SIZE by fixed count BUS_ID_SIZE is being removed from the kernel. Cc: Kay Sievers Signed-off-by: James Bottomley --- drivers/scsi/scsi_transport_fc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 140c50c8a5d2..2eee9e6e4fe8 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3861,7 +3861,7 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host) struct fc_internal *i = to_fc_internal(shost->transportt); struct request_queue *q; int err; - char bsg_name[BUS_ID_SIZE]; /*20*/ + char bsg_name[20]; fc_host->rqst_q = NULL; -- cgit v1.2.3 From 129dd98194747a3b8ac1ff876d8d1f2440660d01 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sun, 21 Jun 2009 23:59:01 +0200 Subject: fusion: mptsas, fix lock imbalance Fix two typos in mptsas_not_responding_devices. It was mutex_lock instead of unlock. Signed-off-by: Jiri Slaby Acked-by: "Desai, Kashyap" Signed-off-by: James Bottomley --- drivers/message/fusion/mptsas.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index 20e0b447e8e8..55ff25244af4 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -3518,7 +3518,7 @@ retry_page: } else mptsas_volume_delete(ioc, sas_info->fw.id); } - mutex_lock(&ioc->sas_device_info_mutex); + mutex_unlock(&ioc->sas_device_info_mutex); /* expanders */ mutex_lock(&ioc->sas_topology_mutex); @@ -3549,7 +3549,7 @@ retry_page: goto redo_expander_scan; } } - mutex_lock(&ioc->sas_topology_mutex); + mutex_unlock(&ioc->sas_topology_mutex); } /** -- cgit v1.2.3